|
|
|
@ -16,8 +16,7 @@ You should have received a copy of the GNU Lesser General Public
|
|
|
|
|
License along with this library; if not, write to the Free Software
|
|
|
|
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
|
|
|
|
|
|
|
|
Sam Lantinga
|
|
|
|
|
slouken@libsdl.org
|
|
|
|
|
Tantric, 2009
|
|
|
|
|
*/
|
|
|
|
|
#include "SDL_config.h"
|
|
|
|
|
|
|
|
|
@ -29,12 +28,16 @@ slouken@libsdl.org
|
|
|
|
|
#include "../SDL_pixels_c.h"
|
|
|
|
|
|
|
|
|
|
// SDL Wii specifics.
|
|
|
|
|
#include <gccore.h>
|
|
|
|
|
#include <ogcsys.h>
|
|
|
|
|
#include <malloc.h>
|
|
|
|
|
#include <ogc/texconv.h>
|
|
|
|
|
#include "SDL_wiivideo.h"
|
|
|
|
|
#include "SDL_wiievents_c.h"
|
|
|
|
|
|
|
|
|
|
static const char WIIVID_DRIVER_NAME[] = "wii";
|
|
|
|
|
static unsigned int y_gamma[256];
|
|
|
|
|
|
|
|
|
|
/*** SDL ***/
|
|
|
|
|
static SDL_Rect mode_320;
|
|
|
|
|
static SDL_Rect mode_640;
|
|
|
|
|
|
|
|
|
@ -45,10 +48,186 @@ static SDL_Rect* modes_descending[] =
|
|
|
|
|
NULL
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/*** 2D Video ***/
|
|
|
|
|
#define HASPECT 320
|
|
|
|
|
#define VASPECT 240
|
|
|
|
|
#define TEXTUREMEM_SIZE (640*480*4)
|
|
|
|
|
|
|
|
|
|
static unsigned int *xfb[2] = { NULL, NULL }; // Double buffered
|
|
|
|
|
static int whichfb = 0; // Switch
|
|
|
|
|
static GXRModeObj* display_mode = 0;
|
|
|
|
|
static unsigned char texturemem[TEXTUREMEM_SIZE] __attribute__((aligned(32))); // GX texture
|
|
|
|
|
|
|
|
|
|
/*** GX ***/
|
|
|
|
|
#define DEFAULT_FIFO_SIZE 256 * 1024
|
|
|
|
|
static unsigned char gp_fifo[DEFAULT_FIFO_SIZE] __attribute__((aligned(32)));
|
|
|
|
|
static GXTexObj texobj;
|
|
|
|
|
static Mtx view;
|
|
|
|
|
|
|
|
|
|
/* 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
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static camera cam = {
|
|
|
|
|
{0.0F, 0.0F, 0.0F},
|
|
|
|
|
{0.0F, 0.5F, 0.0F},
|
|
|
|
|
{0.0F, 0.0F, -0.5F}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/****************************************************************************
|
|
|
|
|
* Scaler Support Functions
|
|
|
|
|
***************************************************************************/
|
|
|
|
|
static void
|
|
|
|
|
draw_init (SDL_Surface *current)
|
|
|
|
|
{
|
|
|
|
|
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);
|
|
|
|
|
|
|
|
|
|
GX_SetTexCoordGen (GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_TEX0, GX_IDENTITY);
|
|
|
|
|
|
|
|
|
|
GX_SetTevOp (GX_TEVSTAGE0, GX_REPLACE);
|
|
|
|
|
GX_SetTevOrder (GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLORNULL);
|
|
|
|
|
|
|
|
|
|
memset (&view, 0, sizeof (Mtx));
|
|
|
|
|
guLookAt(view, &cam.pos, &cam.up, &cam.view);
|
|
|
|
|
GX_LoadPosMtxImm (view, GX_PNMTX0);
|
|
|
|
|
|
|
|
|
|
GX_InvVtxCache (); // update vertex cache
|
|
|
|
|
|
|
|
|
|
// initialize the texture obj we are going to use
|
|
|
|
|
GX_InitTexObj (&texobj, texturemem, current->w, current->h, GX_TF_RGB565, GX_CLAMP, GX_CLAMP, GX_FALSE);
|
|
|
|
|
|
|
|
|
|
// force texture filtering OFF
|
|
|
|
|
//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
|
|
|
|
|
|
|
|
|
|
GX_LoadTexObj (&texobj, GX_TEXMAP0); // load texture object so its ready to use
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static inline void
|
|
|
|
|
draw_vert (u8 pos, u8 c, f32 s, f32 t)
|
|
|
|
|
{
|
|
|
|
|
GX_Position1x8 (pos);
|
|
|
|
|
GX_Color1x8 (c);
|
|
|
|
|
GX_TexCoord2f32 (s, t);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static inline void
|
|
|
|
|
draw_square (Mtx v)
|
|
|
|
|
{
|
|
|
|
|
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 ();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
WII_InitVideoSystem()
|
|
|
|
|
{
|
|
|
|
|
Mtx44 p;
|
|
|
|
|
int df = 1;
|
|
|
|
|
|
|
|
|
|
/* Initialise the video system */
|
|
|
|
|
VIDEO_Init();
|
|
|
|
|
display_mode = VIDEO_GetPreferredMode(NULL);
|
|
|
|
|
/* Set up the video system with the chosen mode */
|
|
|
|
|
VIDEO_Configure(display_mode);
|
|
|
|
|
|
|
|
|
|
// Allocate the video buffers
|
|
|
|
|
xfb[0] = (u32 *) MEM_K0_TO_K1 (SYS_AllocateFramebuffer (display_mode));
|
|
|
|
|
xfb[1] = (u32 *) MEM_K0_TO_K1 (SYS_AllocateFramebuffer (display_mode));
|
|
|
|
|
|
|
|
|
|
// Initialise the debug console.
|
|
|
|
|
console_init(xfb[0],20,20,display_mode->fbWidth,display_mode->xfbHeight,display_mode->fbWidth*VI_DISPLAY_PIX_SZ);
|
|
|
|
|
|
|
|
|
|
VIDEO_ClearFrameBuffer(display_mode, xfb[0], COLOR_BLACK);
|
|
|
|
|
VIDEO_ClearFrameBuffer(display_mode, xfb[1], COLOR_BLACK);
|
|
|
|
|
VIDEO_SetNextFramebuffer (xfb[0]);
|
|
|
|
|
|
|
|
|
|
// Show the screen.
|
|
|
|
|
VIDEO_SetBlack(FALSE);
|
|
|
|
|
VIDEO_Flush();
|
|
|
|
|
VIDEO_WaitVSync();
|
|
|
|
|
if (display_mode->viTVMode & VI_NON_INTERLACE)
|
|
|
|
|
VIDEO_WaitVSync();
|
|
|
|
|
else
|
|
|
|
|
while (VIDEO_GetNextField())
|
|
|
|
|
VIDEO_WaitVSync();
|
|
|
|
|
|
|
|
|
|
/*** Clear out FIFO area ***/
|
|
|
|
|
memset (&gp_fifo, 0, DEFAULT_FIFO_SIZE);
|
|
|
|
|
|
|
|
|
|
/*** Initialise GX ***/
|
|
|
|
|
GX_Init (&gp_fifo, DEFAULT_FIFO_SIZE);
|
|
|
|
|
|
|
|
|
|
GXColor background = { 0, 0, 0, 0xff };
|
|
|
|
|
GX_SetCopyClear (background, 0x00ffffff);
|
|
|
|
|
|
|
|
|
|
GX_SetViewport (0, 0, display_mode->fbWidth, display_mode->efbHeight, 0, 1);
|
|
|
|
|
GX_SetDispCopyYScale ((f32) display_mode->xfbHeight / (f32) display_mode->efbHeight);
|
|
|
|
|
GX_SetScissor (0, 0, display_mode->fbWidth, display_mode->efbHeight);
|
|
|
|
|
|
|
|
|
|
GX_SetDispCopySrc (0, 0, display_mode->fbWidth, display_mode->efbHeight);
|
|
|
|
|
GX_SetDispCopyDst (display_mode->fbWidth, display_mode->xfbHeight);
|
|
|
|
|
GX_SetCopyFilter (display_mode->aa, display_mode->sample_pattern, (df == 1) ? GX_TRUE : GX_FALSE, display_mode->vfilter); // deflicker ON only for filtered mode
|
|
|
|
|
|
|
|
|
|
GX_SetFieldMode (display_mode->field_rendering, ((display_mode->viHeight == 2 * display_mode->xfbHeight) ? GX_ENABLE : GX_DISABLE));
|
|
|
|
|
GX_SetPixelFmt (GX_PF_RGB8_Z24, GX_ZC_LINEAR);
|
|
|
|
|
GX_SetDispCopyGamma (GX_GM_1_0);
|
|
|
|
|
GX_SetCullMode (GX_CULL_NONE);
|
|
|
|
|
GX_SetBlendMode(GX_BM_BLEND,GX_BL_DSTALPHA,GX_BL_INVSRCALPHA,GX_LO_CLEAR);
|
|
|
|
|
|
|
|
|
|
GX_SetZMode (GX_TRUE, GX_LEQUAL, GX_TRUE);
|
|
|
|
|
GX_SetColorUpdate (GX_TRUE);
|
|
|
|
|
|
|
|
|
|
guOrtho(p, display_mode->efbHeight/2, -(display_mode->efbHeight/2), -(display_mode->fbWidth/2), display_mode->fbWidth/2, 100, 1000); // matrix, t, b, l, r, n, f
|
|
|
|
|
GX_LoadProjectionMtx (p, GX_ORTHOGRAPHIC);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int WII_VideoInit(_THIS, SDL_PixelFormat *vformat)
|
|
|
|
|
{
|
|
|
|
|
unsigned int y;
|
|
|
|
|
|
|
|
|
|
// Set up the modes.
|
|
|
|
|
mode_640.w = display_mode->fbWidth;
|
|
|
|
|
mode_640.h = display_mode->xfbHeight;
|
|
|
|
@ -59,11 +238,10 @@ int WII_VideoInit(_THIS, SDL_PixelFormat *vformat)
|
|
|
|
|
vformat->BitsPerPixel = 8;
|
|
|
|
|
vformat->BytesPerPixel = 1;
|
|
|
|
|
|
|
|
|
|
// Initialise the gamma table.
|
|
|
|
|
for (y = 0; y < 256; ++y)
|
|
|
|
|
{
|
|
|
|
|
y_gamma[y] = 255.0f * powf(y / 255.0f, 0.5f);
|
|
|
|
|
}
|
|
|
|
|
this->hidden->buffer = NULL;
|
|
|
|
|
this->hidden->width = 0;
|
|
|
|
|
this->hidden->height = 0;
|
|
|
|
|
this->hidden->pitch = 0;
|
|
|
|
|
|
|
|
|
|
/* We're done! */
|
|
|
|
|
return(0);
|
|
|
|
@ -74,253 +252,76 @@ SDL_Rect **WII_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags)
|
|
|
|
|
return &modes_descending[0];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static inline Wii_Y1CBY2CR PackY1CBY2CR(unsigned int y1, unsigned int cb, unsigned int y2, unsigned int cr)
|
|
|
|
|
{
|
|
|
|
|
return (y1 << 24) | (cb << 16) | (y2 << 8) | cr;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static inline unsigned int CalculateY(unsigned int r, unsigned int g, unsigned int b)
|
|
|
|
|
{
|
|
|
|
|
const unsigned int y = (299 * r + 587 * g + 114 * b) / 1000;
|
|
|
|
|
return y_gamma[y];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static inline unsigned int CalculateCB(unsigned int r, unsigned int g, unsigned int b)
|
|
|
|
|
{
|
|
|
|
|
return (-16874 * r - 33126 * g + 50000 * b + 12800000) / 100000;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static inline unsigned int CalculateCR(unsigned int r, unsigned int g, unsigned int b)
|
|
|
|
|
{
|
|
|
|
|
return (50000 * r - 41869 * g - 8131 * b + 12800000) / 100000;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void UpdateRow_8_1(const void* const src_start, const void* const src_end, Wii_Y1CBY2CR* const dst_start, const Wii_PackedPalette* palette)
|
|
|
|
|
{
|
|
|
|
|
const Uint8* src = src_start;
|
|
|
|
|
Wii_Y1CBY2CR* dst = dst_start;
|
|
|
|
|
while (src != src_end)
|
|
|
|
|
{
|
|
|
|
|
const unsigned int left = *src++;
|
|
|
|
|
const unsigned int right = *src++;
|
|
|
|
|
*dst++ = palette->entries[left][right];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void UpdateRow_8_2(const void* const src_start, const void* const src_end, Wii_Y1CBY2CR* const dst_start, const Wii_PackedPalette* palette)
|
|
|
|
|
{
|
|
|
|
|
const Uint8* src = src_start;
|
|
|
|
|
Wii_Y1CBY2CR* dst = dst_start;
|
|
|
|
|
while (src != src_end)
|
|
|
|
|
{
|
|
|
|
|
const unsigned int left = *src++;
|
|
|
|
|
const unsigned int right = *src++;
|
|
|
|
|
*dst++ = palette->entries[left][left];
|
|
|
|
|
*dst++ = palette->entries[right][right];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static inline Wii_Y1CBY2CR PackRGBs(
|
|
|
|
|
unsigned int r1, unsigned int g1, unsigned int b1,
|
|
|
|
|
unsigned int r2, unsigned int g2, unsigned int b2)
|
|
|
|
|
{
|
|
|
|
|
const unsigned int cb1 = CalculateCB(r1, g1, b1);
|
|
|
|
|
const unsigned int cb2 = CalculateCB(r2, g2, b2);
|
|
|
|
|
const unsigned int cb = (cb1 + cb2) >> 1;
|
|
|
|
|
|
|
|
|
|
const unsigned int cr1 = CalculateCR(r1, g1, b1);
|
|
|
|
|
const unsigned int cr2 = CalculateCR(r2, g2, b2);
|
|
|
|
|
const unsigned int cr = (cr1 + cr2) >> 1;
|
|
|
|
|
|
|
|
|
|
return PackY1CBY2CR(CalculateY(r1, g1, b1), cb, CalculateY(r2, g2, b2), cr);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void UpdateRow_32_1(const void* const src_start, const void* const src_end, Wii_Y1CBY2CR* const dst_start, const Wii_PackedPalette* palette)
|
|
|
|
|
{
|
|
|
|
|
const Uint32* src = src_start;
|
|
|
|
|
Wii_Y1CBY2CR* dst = dst_start;
|
|
|
|
|
while (src != src_end)
|
|
|
|
|
{
|
|
|
|
|
const unsigned int left = *src++;
|
|
|
|
|
const unsigned int r1 = left >> 24;
|
|
|
|
|
const unsigned int g1 = (left >> 16) & 0xff;
|
|
|
|
|
const unsigned int b1 = (left >> 8) & 0xff;
|
|
|
|
|
const unsigned int right = *src++;
|
|
|
|
|
const unsigned int r2 = right >> 24;
|
|
|
|
|
const unsigned int g2 = (right >> 16) & 0xff;
|
|
|
|
|
const unsigned int b2 = (right >> 8) & 0xff;
|
|
|
|
|
*dst++ = PackRGBs(r1, g1, b1, r2, g2, b2);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static inline Wii_Y1CBY2CR PackRGB(unsigned int r, unsigned int g, unsigned int b)
|
|
|
|
|
{
|
|
|
|
|
const unsigned int y = CalculateY(r, g, b);
|
|
|
|
|
const unsigned int cb = CalculateCB(r, g, b);
|
|
|
|
|
const unsigned int cr = CalculateCR(r, g, b);
|
|
|
|
|
|
|
|
|
|
return PackY1CBY2CR(y, cb, y, cr);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void UpdateRow_32_2(const void* const src_start, const void* const src_end, Wii_Y1CBY2CR* const dst_start, const Wii_PackedPalette* palette)
|
|
|
|
|
{
|
|
|
|
|
const Uint32* src = src_start;
|
|
|
|
|
Wii_Y1CBY2CR* dst = dst_start;
|
|
|
|
|
while (src != src_end)
|
|
|
|
|
{
|
|
|
|
|
const unsigned int left = *src++;
|
|
|
|
|
const unsigned int r1 = left >> 24;
|
|
|
|
|
const unsigned int g1 = (left >> 16) & 0xff;
|
|
|
|
|
const unsigned int b1 = (left >> 8) & 0xff;
|
|
|
|
|
const unsigned int right = *src++;
|
|
|
|
|
const unsigned int r2 = right >> 24;
|
|
|
|
|
const unsigned int g2 = (right >> 16) & 0xff;
|
|
|
|
|
const unsigned int b2 = (right >> 8) & 0xff;
|
|
|
|
|
*dst++ = PackRGB(r1, g1, b1);
|
|
|
|
|
*dst++ = PackRGB(r2, g2, b2);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
SDL_Surface *WII_SetVideoMode(_THIS, SDL_Surface *current,
|
|
|
|
|
int width, int height, int bpp, Uint32 flags)
|
|
|
|
|
{
|
|
|
|
|
typedef struct ModeInfo
|
|
|
|
|
{
|
|
|
|
|
const SDL_Rect* resolution;
|
|
|
|
|
unsigned int magnification;
|
|
|
|
|
WII_UpdateRowFn* update_row_8;
|
|
|
|
|
WII_UpdateRowFn* update_row_32;
|
|
|
|
|
} ModeInfo;
|
|
|
|
|
|
|
|
|
|
static const ModeInfo modes_ascending[] =
|
|
|
|
|
{
|
|
|
|
|
{ &mode_320, 2, &UpdateRow_8_2, &UpdateRow_32_2 },
|
|
|
|
|
{ &mode_640, 1, &UpdateRow_8_1, &UpdateRow_32_1 },
|
|
|
|
|
{ NULL }
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const ModeInfo* mode;
|
|
|
|
|
SDL_Rect* mode;
|
|
|
|
|
size_t bytes_per_pixel;
|
|
|
|
|
Uint32 r_mask;
|
|
|
|
|
Uint32 b_mask;
|
|
|
|
|
Uint32 g_mask;
|
|
|
|
|
WII_UpdateRowFn* update_row;
|
|
|
|
|
Uint32 r_mask = 0;
|
|
|
|
|
Uint32 b_mask = 0;
|
|
|
|
|
Uint32 g_mask = 0;
|
|
|
|
|
|
|
|
|
|
/* Find a mode big enough to store the requested resolution */
|
|
|
|
|
mode = &modes_ascending[0];
|
|
|
|
|
while (mode->resolution)
|
|
|
|
|
{
|
|
|
|
|
if ((mode->resolution->w >= width) && (mode->resolution->h >= height))
|
|
|
|
|
mode = modes_descending[0];
|
|
|
|
|
while (mode)
|
|
|
|
|
{
|
|
|
|
|
if ((mode->w >= width) && (mode->h >= height))
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
++mode;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Didn't find a mode?
|
|
|
|
|
if (!mode->resolution)
|
|
|
|
|
if (!mode)
|
|
|
|
|
{
|
|
|
|
|
SDL_SetError("Display mode (%dx%d) is too large to fit on the screen (%dx%d)",
|
|
|
|
|
width, height, modes_descending[0]->w, modes_descending[0]->h);
|
|
|
|
|
SDL_SetError("Display mode (%dx%d) is too large to fit on the screen",
|
|
|
|
|
width, height);
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Handle the bpp */
|
|
|
|
|
if (bpp <= 8)
|
|
|
|
|
{
|
|
|
|
|
bpp = 8;
|
|
|
|
|
r_mask = 0;
|
|
|
|
|
g_mask = 0;
|
|
|
|
|
b_mask = 0;
|
|
|
|
|
update_row = mode->update_row_8;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
bpp = 32;
|
|
|
|
|
r_mask = 0xff000000;
|
|
|
|
|
g_mask = 0xff0000;
|
|
|
|
|
b_mask = 0xff00;
|
|
|
|
|
update_row = mode->update_row_32;
|
|
|
|
|
}
|
|
|
|
|
bytes_per_pixel = bpp / 8;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Free any existing buffer.
|
|
|
|
|
if (this->hidden->back_buffer)
|
|
|
|
|
if (this->hidden->buffer)
|
|
|
|
|
{
|
|
|
|
|
SDL_free(this->hidden->back_buffer);
|
|
|
|
|
this->hidden->back_buffer = NULL;
|
|
|
|
|
free(this->hidden->buffer);
|
|
|
|
|
this->hidden->buffer = NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (this->hidden->tmp_buffer)
|
|
|
|
|
{
|
|
|
|
|
SDL_free(this->hidden->tmp_buffer);
|
|
|
|
|
this->hidden->tmp_buffer = NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Allocate the new buffer.
|
|
|
|
|
this->hidden->back_buffer = SDL_malloc(width * height * bytes_per_pixel);
|
|
|
|
|
if (!this->hidden->back_buffer )
|
|
|
|
|
this->hidden->buffer = memalign(32, width * height * bytes_per_pixel);
|
|
|
|
|
if (!this->hidden->buffer )
|
|
|
|
|
{
|
|
|
|
|
SDL_SetError("Couldn't allocate buffer for requested mode");
|
|
|
|
|
return(NULL);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
this->hidden->tmp_buffer = SDL_malloc((width+4) * (height+4) * bytes_per_pixel);
|
|
|
|
|
if (!this->hidden->tmp_buffer )
|
|
|
|
|
{
|
|
|
|
|
SDL_free(this->hidden->back_buffer);
|
|
|
|
|
this->hidden->back_buffer = NULL;
|
|
|
|
|
SDL_SetError("Couldn't allocate buffer for requested mode");
|
|
|
|
|
return(NULL);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Allocate the new pixel format for the screen */
|
|
|
|
|
// Allocate the new pixel format for the screen
|
|
|
|
|
if (!SDL_ReallocFormat(current, bpp, r_mask, g_mask, b_mask, 0))
|
|
|
|
|
{
|
|
|
|
|
SDL_free(this->hidden->back_buffer);
|
|
|
|
|
this->hidden->back_buffer = NULL;
|
|
|
|
|
SDL_free(this->hidden->tmp_buffer);
|
|
|
|
|
this->hidden->tmp_buffer = NULL;
|
|
|
|
|
free(this->hidden->buffer);
|
|
|
|
|
this->hidden->buffer = NULL;
|
|
|
|
|
|
|
|
|
|
SDL_SetError("Couldn't allocate new pixel format for requested mode");
|
|
|
|
|
return(NULL);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Clear the back buffer.
|
|
|
|
|
SDL_memset(this->hidden->back_buffer, 0, width * height * bytes_per_pixel);
|
|
|
|
|
SDL_memset(this->hidden->tmp_buffer, 0, width * height * bytes_per_pixel);
|
|
|
|
|
// Clear the buffer
|
|
|
|
|
SDL_memset(this->hidden->buffer, 0, width * height * bytes_per_pixel);
|
|
|
|
|
|
|
|
|
|
/* Set up the new mode framebuffer */
|
|
|
|
|
//current->flags = SDL_DOUBLEBUF |( flags & SDL_FULLSCREEN);
|
|
|
|
|
current->flags = flags & SDL_FULLSCREEN;
|
|
|
|
|
// Set up the new mode framebuffer
|
|
|
|
|
current->flags = SDL_DOUBLEBUF |( flags & SDL_FULLSCREEN);
|
|
|
|
|
current->w = width;
|
|
|
|
|
current->h = height;
|
|
|
|
|
current->pitch = current->w * bytes_per_pixel;
|
|
|
|
|
current->pixels = this->hidden->back_buffer;
|
|
|
|
|
current->pixels = this->hidden->buffer;
|
|
|
|
|
|
|
|
|
|
/* Set the hidden data */
|
|
|
|
|
this->hidden->update_row = update_row;
|
|
|
|
|
this->hidden->magnification = mode->magnification;
|
|
|
|
|
this->hidden->width = current->w;
|
|
|
|
|
this->hidden->height = current->h;
|
|
|
|
|
this->hidden->pitch = current->pitch;
|
|
|
|
|
|
|
|
|
|
#if 0
|
|
|
|
|
// Clear the frame buffer.
|
|
|
|
|
for (y = 0; y < display_mode->xfbHeight; ++y)
|
|
|
|
|
{
|
|
|
|
|
unsigned int x;
|
|
|
|
|
for (x = 0; x < (display_mode->fbWidth / 2); ++x)
|
|
|
|
|
{
|
|
|
|
|
static const Wii_Y1CBY2CR black = PackRGB(0, 0, 0);
|
|
|
|
|
(*frame_buffer)[y][x] = black;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
draw_init(current);
|
|
|
|
|
|
|
|
|
|
/* We're done */
|
|
|
|
|
return(current);
|
|
|
|
@ -347,197 +348,85 @@ static void WII_UnlockHWSurface(_THIS, SDL_Surface *surface)
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void WII_FlipHWSurface(_THIS, SDL_Surface *surface)
|
|
|
|
|
static int WII_FlipHWSurface(_THIS, SDL_Surface *surface)
|
|
|
|
|
{
|
|
|
|
|
Wii_Y1CBY2CR (*now)[][320] = 0;
|
|
|
|
|
now = frame_buffer;
|
|
|
|
|
if (frame_buffer==frame_buffer1) {
|
|
|
|
|
frame_buffer = frame_buffer2;
|
|
|
|
|
//this->hidden->back_buffer = frame_buffer1;
|
|
|
|
|
//surface->pixels = frame_buffer1;
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
frame_buffer = frame_buffer1;
|
|
|
|
|
//this->hidden->back_buffer = frame_buffer2;
|
|
|
|
|
//surface->pixels = frame_buffer2;
|
|
|
|
|
int h, w;
|
|
|
|
|
long long int *dst = (long long int *) texturemem;
|
|
|
|
|
long long int *src1 = (long long int *) this->hidden->buffer;
|
|
|
|
|
long long int *src2 = (long long int *) (this->hidden->buffer + this->hidden->pitch);
|
|
|
|
|
long long int *src3 = (long long int *) (this->hidden->buffer + (this->hidden->pitch * 2));
|
|
|
|
|
long long int *src4 = (long long int *) (this->hidden->buffer + (this->hidden->pitch * 3));
|
|
|
|
|
int rowpitch = (this->hidden->pitch >> 3) * 3;
|
|
|
|
|
int rowadjust = (this->hidden->pitch % 8) * 4;
|
|
|
|
|
char *ra = NULL;
|
|
|
|
|
|
|
|
|
|
whichfb ^= 1;
|
|
|
|
|
|
|
|
|
|
// clear texture objects
|
|
|
|
|
GX_InvVtxCache();
|
|
|
|
|
GX_InvalidateTexAll();
|
|
|
|
|
|
|
|
|
|
for (h = 0; h < this->hidden->height; h += 4)
|
|
|
|
|
{
|
|
|
|
|
for (w = 0; w < (this->hidden->width >> 2); w++)
|
|
|
|
|
{
|
|
|
|
|
*dst++ = *src1++;
|
|
|
|
|
*dst++ = *src2++;
|
|
|
|
|
*dst++ = *src3++;
|
|
|
|
|
*dst++ = *src4++;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
VIDEO_SetNextFramebuffer(now);
|
|
|
|
|
src1 += rowpitch;
|
|
|
|
|
src2 += rowpitch;
|
|
|
|
|
src3 += rowpitch;
|
|
|
|
|
src4 += rowpitch;
|
|
|
|
|
|
|
|
|
|
if ( rowadjust )
|
|
|
|
|
{
|
|
|
|
|
ra = (char *)src1;
|
|
|
|
|
src1 = (long long int *)(ra + rowadjust);
|
|
|
|
|
ra = (char *)src2;
|
|
|
|
|
src2 = (long long int *)(ra + rowadjust);
|
|
|
|
|
ra = (char *)src3;
|
|
|
|
|
src3 = (long long int *)(ra + rowadjust);
|
|
|
|
|
ra = (char *)src4;
|
|
|
|
|
src4 = (long long int *)(ra + rowadjust);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// load texture into GX
|
|
|
|
|
DCFlushRange(texturemem, TEXTUREMEM_SIZE);
|
|
|
|
|
|
|
|
|
|
GX_SetNumChans(1);
|
|
|
|
|
GX_LoadTexObj(&texobj, GX_TEXMAP0);
|
|
|
|
|
|
|
|
|
|
draw_square(view); // render textured quad
|
|
|
|
|
GX_DrawDone ();
|
|
|
|
|
GX_CopyDisp(xfb[whichfb], GX_TRUE);
|
|
|
|
|
GX_Flush();
|
|
|
|
|
VIDEO_SetNextFramebuffer(xfb[whichfb]);
|
|
|
|
|
VIDEO_Flush();
|
|
|
|
|
VIDEO_WaitVSync();
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Uint32 blur(Uint32 now, Uint32 above, Uint32 below)
|
|
|
|
|
{
|
|
|
|
|
const Uint32 R = 0xff000000;
|
|
|
|
|
const Uint32 G = 0x00ff0000;
|
|
|
|
|
const Uint32 B = 0x0000ff00;
|
|
|
|
|
|
|
|
|
|
int r = ((((now & R)>>24)<<1) + ((above & R)>>24) + ((below & R)>>24))>>2;
|
|
|
|
|
int g = ((((now & G)>>16)<<1) + ((above & G)>>16) + ((below & G)>>16))>>2;
|
|
|
|
|
int b = ((((now & B)>>8)<<1) + ((above & B)>>8) + ((below & B)>>8))>>2;
|
|
|
|
|
|
|
|
|
|
if (r>255) r = 255;
|
|
|
|
|
if (g>255) g = 255;
|
|
|
|
|
if (b>255) b = 255;
|
|
|
|
|
return r << 24 | g <<16 | b <<8;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void UpdateRect(_THIS, const SDL_Rect* const rect)
|
|
|
|
|
{
|
|
|
|
|
const SDL_Surface* const screen = this->screen;
|
|
|
|
|
|
|
|
|
|
if (screen)
|
|
|
|
|
{
|
|
|
|
|
// Constants.
|
|
|
|
|
const unsigned int x = rect->x;
|
|
|
|
|
const unsigned int y = rect->y;
|
|
|
|
|
const unsigned int w = rect->w;
|
|
|
|
|
const unsigned int h = rect->h;
|
|
|
|
|
const struct SDL_PrivateVideoData* const hidden = this->hidden;
|
|
|
|
|
WII_UpdateRowFn* const update_row = hidden->update_row;
|
|
|
|
|
const unsigned int magnification = hidden->magnification;
|
|
|
|
|
const Wii_PackedPalette* const palette = &hidden->packed_palette;
|
|
|
|
|
const unsigned int src_bytes_per_pixel = screen->format->BytesPerPixel;
|
|
|
|
|
const unsigned int src_pitch = screen->pitch;
|
|
|
|
|
const Wii_Y1CBY2CR* const last_dst_row = &(*frame_buffer)[(y + h) * magnification][(x * magnification) / 2];
|
|
|
|
|
|
|
|
|
|
// These variables change per row.
|
|
|
|
|
const Uint8* src_row_start = &hidden->back_buffer[(y * src_pitch) + (x * src_bytes_per_pixel)];
|
|
|
|
|
const Uint8* src_row_end = src_row_start + (w * src_bytes_per_pixel);
|
|
|
|
|
Wii_Y1CBY2CR* dst_row_start = &(*frame_buffer)[y * magnification][(x * magnification) / 2];
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Uint32* src = (Uint32*)&hidden->back_buffer[(y * src_pitch) + (x * src_bytes_per_pixel)];
|
|
|
|
|
|
|
|
|
|
Uint32* dst = (Uint32*)&hidden->tmp_buffer[(y * screen->w) + x ];
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (src_bytes_per_pixel==4) {
|
|
|
|
|
int i,j;
|
|
|
|
|
for (i=0; i<h; i++) {
|
|
|
|
|
Uint32* srctmp = src;
|
|
|
|
|
Uint32* dsttmp = dst;
|
|
|
|
|
for (j=0; j<w; j++) {
|
|
|
|
|
register int above = (i<=0)?0:src[-screen->w];
|
|
|
|
|
register int below = (i>=screen->h-1)?0:src[screen->w];
|
|
|
|
|
*dst = blur(*src,above,below);
|
|
|
|
|
//*dst = *src;
|
|
|
|
|
src++;
|
|
|
|
|
dst++;
|
|
|
|
|
}
|
|
|
|
|
src = srctmp + screen->w;
|
|
|
|
|
dst = dsttmp + screen->w;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
src_row_start = &hidden->tmp_buffer[(y * screen->w) + (x)];
|
|
|
|
|
src_row_end = src_row_start + (w * src_bytes_per_pixel);
|
|
|
|
|
|
|
|
|
|
// Update each row.
|
|
|
|
|
while (dst_row_start != last_dst_row)
|
|
|
|
|
{
|
|
|
|
|
// Update this row.
|
|
|
|
|
update_row(src_row_start, src_row_end, dst_row_start, palette);
|
|
|
|
|
if (magnification == 1)
|
|
|
|
|
{
|
|
|
|
|
// No magnification, just move on to the next row.
|
|
|
|
|
dst_row_start += 320;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
unsigned int i;
|
|
|
|
|
Wii_Y1CBY2CR* next_row = dst_row_start + 320;
|
|
|
|
|
|
|
|
|
|
// Copy each magnified row.
|
|
|
|
|
for (i = 1; i < magnification; ++i)
|
|
|
|
|
{
|
|
|
|
|
memcpy(next_row, dst_row_start, 320 * sizeof(Wii_Y1CBY2CR));
|
|
|
|
|
next_row += 320;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Move on to the next unmagnified row.
|
|
|
|
|
dst_row_start = next_row;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Move on to the next row.
|
|
|
|
|
src_row_start += src_pitch;
|
|
|
|
|
src_row_end += src_pitch;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return(1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void WII_UpdateRects(_THIS, int numrects, SDL_Rect *rects)
|
|
|
|
|
{
|
|
|
|
|
const SDL_Rect* rect;
|
|
|
|
|
const SDL_Rect* const last_rect = &rects[numrects];
|
|
|
|
|
|
|
|
|
|
/* Update each rect */
|
|
|
|
|
for (rect = rects; rect != last_rect; ++rect)
|
|
|
|
|
{
|
|
|
|
|
/* Because we pack pixels together we need to align the rect. */
|
|
|
|
|
const Sint16 x1 = rect->x & ~1;
|
|
|
|
|
const Sint16 x2 = (rect->x + rect->w + 1) & ~1;
|
|
|
|
|
const SDL_Rect aligned_rect = {x1, rect->y, x2 - x1, rect->h};
|
|
|
|
|
|
|
|
|
|
UpdateRect(this, &aligned_rect);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int WII_SetColors(_THIS, int first_color, int color_count, SDL_Color *colors)
|
|
|
|
|
{
|
|
|
|
|
const int last_color = first_color + color_count;
|
|
|
|
|
Wii_Palette* const palette = &this->hidden->palette;
|
|
|
|
|
Wii_PackedPalette* const packed_palette = &this->hidden->packed_palette;
|
|
|
|
|
|
|
|
|
|
int component;
|
|
|
|
|
int left;
|
|
|
|
|
int right;
|
|
|
|
|
|
|
|
|
|
/* Build the YCBCR palette. */
|
|
|
|
|
for (component = first_color; component != last_color; ++component)
|
|
|
|
|
{
|
|
|
|
|
const SDL_Color* const in = &colors[component - first_color];
|
|
|
|
|
const unsigned int r = in->r;
|
|
|
|
|
const unsigned int g = in->g;
|
|
|
|
|
const unsigned int b = in->b;
|
|
|
|
|
(*palette)[component].y = CalculateY(r, g, b);
|
|
|
|
|
(*palette)[component].cb = CalculateCB(r, g, b);
|
|
|
|
|
(*palette)[component].cr = CalculateCR(r, g, b);
|
|
|
|
|
return(0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Build the Y1CBY2CR palette from the YCBCR palette. */
|
|
|
|
|
// @todo optimise - not all of the entries require recalculation.
|
|
|
|
|
for (left = 0; left != 256; ++left)
|
|
|
|
|
{
|
|
|
|
|
const unsigned int y1 = (*palette)[left].y;
|
|
|
|
|
const unsigned int cb1 = (*palette)[left].cb;
|
|
|
|
|
const unsigned int cr1 = (*palette)[left].cr;
|
|
|
|
|
for (right = 0; right != 256; ++right)
|
|
|
|
|
{
|
|
|
|
|
const unsigned int cb = (cb1 + (*palette)[right].cb) >> 1;
|
|
|
|
|
const unsigned int cr = (cr1 + (*palette)[right].cr) >> 1;
|
|
|
|
|
(*packed_palette).entries[left][right] = PackY1CBY2CR(y1, cb, (*palette)[right].y, cr);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return(1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Note: If we are terminated, this could be called in the middle of
|
|
|
|
|
another SDL video routine -- notably UpdateRects.
|
|
|
|
|
*/
|
|
|
|
|
void WII_VideoQuit(_THIS)
|
|
|
|
|
{
|
|
|
|
|
/* if (this->screen->pixels != NULL)
|
|
|
|
|
{
|
|
|
|
|
SDL_free(this->screen->pixels);
|
|
|
|
|
this->screen->pixels = NULL;
|
|
|
|
|
}*/
|
|
|
|
|
GX_AbortFrame();
|
|
|
|
|
GX_Flush();
|
|
|
|
|
|
|
|
|
|
VIDEO_SetBlack(TRUE);
|
|
|
|
|
VIDEO_Flush();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void WII_DeleteDevice(SDL_VideoDevice *device)
|
|
|
|
@ -581,8 +470,7 @@ static SDL_VideoDevice *WII_CreateDevice(int devindex)
|
|
|
|
|
device->SetHWAlpha = NULL;
|
|
|
|
|
device->LockHWSurface = WII_LockHWSurface;
|
|
|
|
|
device->UnlockHWSurface = WII_UnlockHWSurface;
|
|
|
|
|
//device->FlipHWSurface = WII_FlipHWSurface;
|
|
|
|
|
device->FlipHWSurface = NULL;
|
|
|
|
|
device->FlipHWSurface = WII_FlipHWSurface;
|
|
|
|
|
device->FreeHWSurface = WII_FreeHWSurface;
|
|
|
|
|
device->SetCaption = NULL;
|
|
|
|
|
device->SetIcon = NULL;
|
|
|
|
|