rewrite video system to use GX

This commit is contained in:
dborth 2009-04-28 21:34:53 +00:00
parent c60046e30b
commit b42793c03c
6 changed files with 308 additions and 495 deletions

View file

@ -15,7 +15,7 @@ LIB_DIR := lib
BIN_DIR := bin/wii
SDL_OBJ_DIR := $(OBJ_DIR)/sdl
SDL_SRC_DIR := src
INSTALL_HEADER_DIR ?= $(DEVKITPRO)/libogc/include/
INSTALL_HEADER_DIR ?= $(DEVKITPRO)/libogc/include
INSTALL_LIB_DIR ?= $(DEVKITPRO)/libogc/lib/wii
# Tools.

View file

@ -1,17 +0,0 @@
The SDL port to the Nintendo Wii
This port uses the devKitPro toolchain, available from:
http://www.devkitpro.org
todo:
use gx for display
use libfat for file access
build with:
cp include/SDL_config_wii.h include/SDL_config.h
make -f Makefile.wii
Original SDL gamecube port - taken from www.devkitpro.org
Port to Wii by mindcry (http://mindcry.cpl.de/wii/)
Many fixes (threading, audio among other stuff) by Yohanes Nugroho (http://tinyhack.com)
Renamed everything from GameCube to Wii. Built against SDL SVN - David Hudson (http://cs-sdl.sourceforge.net)

View file

@ -12,25 +12,14 @@
#include <ogcsys.h>
#include <wiiuse/wpad.h>
/* Globals */
GXRModeObj* display_mode = 0;
Wii_Y1CBY2CR (*frame_buffer1)[][320] = 0;
Wii_Y1CBY2CR (*frame_buffer2)[][320] = 0;
Wii_Y1CBY2CR (*frame_buffer)[][320] = 0;
extern void wii_keyboard_init();
extern void wii_mouse_init();
/* Do initialisation which has to be done first for the console to work */
static void WII_Init(void)
/* Entry point */
int main(int argc, char *argv[])
{
//printf("WII_Init ENTER\n");
/* Initialise the video system */
VIDEO_Init();
display_mode = VIDEO_GetPreferredMode(NULL);
WII_InitVideoSystem();
WPAD_Init();
PAD_Init();
@ -38,49 +27,12 @@ static void WII_Init(void)
WPAD_SetDataFormat(0, WPAD_FMT_BTNS_ACC_IR);
WPAD_SetVRes(0, 640, 480);
/* Allocate the frame buffer */
frame_buffer1 = (Wii_Y1CBY2CR (*)[][320])(MEM_K0_TO_K1(SYS_AllocateFramebuffer(display_mode)));
//frame_buffer2 = (Wii_Y1CBY2CR (*)[][320])(MEM_K0_TO_K1(SYS_AllocateFramebuffer(display_mode)));
frame_buffer = frame_buffer1;
/* Set up the video system with the chosen mode */
VIDEO_Configure(display_mode);
/* Set the frame buffer */
VIDEO_SetNextFramebuffer(frame_buffer);
// Show the screen.
VIDEO_SetBlack(FALSE);
VIDEO_Flush();
VIDEO_WaitVSync();
if (display_mode->viTVMode & VI_NON_INTERLACE)
{
VIDEO_WaitVSync();
}
// Initialise the debug console.
console_init(frame_buffer,20,20,display_mode->fbWidth,display_mode->xfbHeight,display_mode->fbWidth*VI_DISPLAY_PIX_SZ);
USB_Initialize();
wii_mouse_init(); //must be called first
wii_keyboard_init();
//printf("WII_Init EXIT\n");
}
/* Entry point */
int main(int argc, char *argv[])
{
printf("main ENTER\n");
/* Set up the screen mode */
WII_Init();
/* Call the user's main function */
return(SDL_main(argc, argv));
printf("main EXIT\n");
}
/* This function isn't implemented */

View file

@ -1,23 +1,22 @@
/*
SDL - Simple DirectMedia Layer
Copyright (C) 1997-2006 Sam Lantinga
SDL - Simple DirectMedia Layer
Copyright (C) 1997-2006 Sam Lantinga
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
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
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;
size_t bytes_per_pixel;
Uint32 r_mask;
Uint32 b_mask;
Uint32 g_mask;
WII_UpdateRowFn* update_row;
SDL_Rect* mode;
size_t bytes_per_pixel;
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)
mode = modes_descending[0];
while (mode)
{
if ((mode->resolution->w >= width) && (mode->resolution->h >= height))
{
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;
VIDEO_SetNextFramebuffer(now);
VIDEO_Flush();
VIDEO_WaitVSync();
whichfb ^= 1;
}
// clear texture objects
GX_InvVtxCache();
GX_InvalidateTexAll();
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)
for (h = 0; h < this->hidden->height; h += 4)
{
// 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;
}
for (w = 0; w < (this->hidden->width >> 2); w++)
{
*dst++ = *src1++;
*dst++ = *src2++;
*dst++ = *src3++;
*dst++ = *src4++;
}
src1 += rowpitch;
src2 += rowpitch;
src3 += rowpitch;
src4 += rowpitch;
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)
if ( rowadjust )
{
// 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;
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();
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);
}
/* 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);
return(0);
}
/* 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;

View file

@ -16,8 +16,7 @@
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"
@ -33,37 +32,15 @@
/* Hidden "this" pointer for the video functions */
#define _THIS SDL_VideoDevice *this
/* The Wii uses this frame buffer format */
typedef Uint32 Wii_Y1CBY2CR;
/* A single palette entry */
typedef struct Wii_YCBCR
{
Uint8 y;
Uint8 cb;
Uint8 cr;
} Wii_YCBCR;
/* Types */
typedef Wii_YCBCR Wii_Palette[256];
typedef struct { Wii_Y1CBY2CR entries[256][256]; } Wii_PackedPalette;
typedef void (WII_UpdateRowFn)(const void*, const void*, Wii_Y1CBY2CR*, const Wii_PackedPalette*);
/* Private display data */
struct SDL_PrivateVideoData
{
Uint8* back_buffer;
Uint32* tmp_buffer;
Wii_Palette palette;
Wii_PackedPalette packed_palette;
WII_UpdateRowFn* update_row;
unsigned int magnification;
Uint8* buffer;
int width;
int height;
int pitch;
};
/* Globals */
extern GXRModeObj* display_mode;
extern Wii_Y1CBY2CR (*frame_buffer)[][320];
extern Wii_Y1CBY2CR (*frame_buffer1)[][320];
extern Wii_Y1CBY2CR (*frame_buffer2)[][320];
void WII_InitVideoSystem();
#endif /* _SDL_wiivideo_h */

13
readme.txt Normal file
View file

@ -0,0 +1,13 @@
Port of SDL for the Nintendo Wii
http://code.google.com/p/sdl-wii/
This port uses the devKitPro toolchain, available from:
http://www.devkitpro.org
Credits
Original GameCube port www.devkitpro.org
Ported to Wii Mindcry (http://mindcry.cpl.de/wii/)
Many fixes (threading, audio, etc) Yohanes Nugroho (http://tinyhack.com)
Renamed to Wii, update to SDL SVN David Hudson (http://cs-sdl.sourceforge.net)
Audio + Video (using GX) systems rewrite Tantric