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 BIN_DIR := bin/wii
SDL_OBJ_DIR := $(OBJ_DIR)/sdl SDL_OBJ_DIR := $(OBJ_DIR)/sdl
SDL_SRC_DIR := src SDL_SRC_DIR := src
INSTALL_HEADER_DIR ?= $(DEVKITPRO)/libogc/include/ INSTALL_HEADER_DIR ?= $(DEVKITPRO)/libogc/include
INSTALL_LIB_DIR ?= $(DEVKITPRO)/libogc/lib/wii INSTALL_LIB_DIR ?= $(DEVKITPRO)/libogc/lib/wii
# Tools. # 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 <ogcsys.h>
#include <wiiuse/wpad.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_keyboard_init();
extern void wii_mouse_init(); extern void wii_mouse_init();
/* Do initialisation which has to be done first for the console to work */ /* 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"); WII_InitVideoSystem();
/* Initialise the video system */
VIDEO_Init();
display_mode = VIDEO_GetPreferredMode(NULL);
WPAD_Init(); WPAD_Init();
PAD_Init(); PAD_Init();
@ -38,49 +27,12 @@ static void WII_Init(void)
WPAD_SetDataFormat(0, WPAD_FMT_BTNS_ACC_IR); WPAD_SetDataFormat(0, WPAD_FMT_BTNS_ACC_IR);
WPAD_SetVRes(0, 640, 480); 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(); USB_Initialize();
wii_mouse_init(); //must be called first wii_mouse_init(); //must be called first
wii_keyboard_init(); 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 */ /* Call the user's main function */
return(SDL_main(argc, argv)); return(SDL_main(argc, argv));
printf("main EXIT\n");
} }
/* This function isn't implemented */ /* This function isn't implemented */

View file

@ -1,23 +1,22 @@
/* /*
SDL - Simple DirectMedia Layer SDL - Simple DirectMedia Layer
Copyright (C) 1997-2006 Sam Lantinga Copyright (C) 1997-2006 Sam Lantinga
This library is free software; you can redistribute it and/or This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version. 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, This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details. Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
Sam Lantinga Tantric, 2009
slouken@libsdl.org
*/ */
#include "SDL_config.h" #include "SDL_config.h"
@ -29,12 +28,16 @@ slouken@libsdl.org
#include "../SDL_pixels_c.h" #include "../SDL_pixels_c.h"
// SDL Wii specifics. // SDL Wii specifics.
#include <gccore.h>
#include <ogcsys.h>
#include <malloc.h>
#include <ogc/texconv.h>
#include "SDL_wiivideo.h" #include "SDL_wiivideo.h"
#include "SDL_wiievents_c.h" #include "SDL_wiievents_c.h"
static const char WIIVID_DRIVER_NAME[] = "wii"; static const char WIIVID_DRIVER_NAME[] = "wii";
static unsigned int y_gamma[256];
/*** SDL ***/
static SDL_Rect mode_320; static SDL_Rect mode_320;
static SDL_Rect mode_640; static SDL_Rect mode_640;
@ -45,10 +48,186 @@ static SDL_Rect* modes_descending[] =
NULL 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) int WII_VideoInit(_THIS, SDL_PixelFormat *vformat)
{ {
unsigned int y;
// Set up the modes. // Set up the modes.
mode_640.w = display_mode->fbWidth; mode_640.w = display_mode->fbWidth;
mode_640.h = display_mode->xfbHeight; mode_640.h = display_mode->xfbHeight;
@ -59,11 +238,10 @@ int WII_VideoInit(_THIS, SDL_PixelFormat *vformat)
vformat->BitsPerPixel = 8; vformat->BitsPerPixel = 8;
vformat->BytesPerPixel = 1; vformat->BytesPerPixel = 1;
// Initialise the gamma table. this->hidden->buffer = NULL;
for (y = 0; y < 256; ++y) this->hidden->width = 0;
{ this->hidden->height = 0;
y_gamma[y] = 255.0f * powf(y / 255.0f, 0.5f); this->hidden->pitch = 0;
}
/* We're done! */ /* We're done! */
return(0); return(0);
@ -74,253 +252,76 @@ SDL_Rect **WII_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags)
return &modes_descending[0]; 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, SDL_Surface *WII_SetVideoMode(_THIS, SDL_Surface *current,
int width, int height, int bpp, Uint32 flags) int width, int height, int bpp, Uint32 flags)
{ {
typedef struct ModeInfo SDL_Rect* mode;
{
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; size_t bytes_per_pixel;
Uint32 r_mask; Uint32 r_mask = 0;
Uint32 b_mask; Uint32 b_mask = 0;
Uint32 g_mask; Uint32 g_mask = 0;
WII_UpdateRowFn* update_row;
/* Find a mode big enough to store the requested resolution */ /* Find a mode big enough to store the requested resolution */
mode = &modes_ascending[0]; mode = modes_descending[0];
while (mode->resolution) while (mode)
{
if ((mode->resolution->w >= width) && (mode->resolution->h >= height))
{ {
if ((mode->w >= width) && (mode->h >= height))
break; break;
}
else else
{
++mode; ++mode;
} }
}
// Didn't find a 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)", SDL_SetError("Display mode (%dx%d) is too large to fit on the screen",
width, height, modes_descending[0]->w, modes_descending[0]->h); width, height);
return NULL; 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; bytes_per_pixel = bpp / 8;
// Free any existing buffer. // Free any existing buffer.
if (this->hidden->back_buffer) if (this->hidden->buffer)
{ {
SDL_free(this->hidden->back_buffer); free(this->hidden->buffer);
this->hidden->back_buffer = NULL; this->hidden->buffer = NULL;
} }
if (this->hidden->tmp_buffer)
{
SDL_free(this->hidden->tmp_buffer);
this->hidden->tmp_buffer = NULL;
}
// Allocate the new buffer. // Allocate the new buffer.
this->hidden->back_buffer = SDL_malloc(width * height * bytes_per_pixel); this->hidden->buffer = memalign(32, width * height * bytes_per_pixel);
if (!this->hidden->back_buffer ) if (!this->hidden->buffer )
{ {
SDL_SetError("Couldn't allocate buffer for requested mode"); SDL_SetError("Couldn't allocate buffer for requested mode");
return(NULL); return(NULL);
} }
this->hidden->tmp_buffer = SDL_malloc((width+4) * (height+4) * bytes_per_pixel); // Allocate the new pixel format for the screen
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 */
if (!SDL_ReallocFormat(current, bpp, r_mask, g_mask, b_mask, 0)) if (!SDL_ReallocFormat(current, bpp, r_mask, g_mask, b_mask, 0))
{ {
SDL_free(this->hidden->back_buffer); free(this->hidden->buffer);
this->hidden->back_buffer = NULL; this->hidden->buffer = NULL;
SDL_free(this->hidden->tmp_buffer);
this->hidden->tmp_buffer = NULL;
SDL_SetError("Couldn't allocate new pixel format for requested mode"); SDL_SetError("Couldn't allocate new pixel format for requested mode");
return(NULL); return(NULL);
} }
// Clear the back buffer. // Clear the buffer
SDL_memset(this->hidden->back_buffer, 0, width * height * bytes_per_pixel); SDL_memset(this->hidden->buffer, 0, width * height * bytes_per_pixel);
SDL_memset(this->hidden->tmp_buffer, 0, width * height * bytes_per_pixel);
/* Set up the new mode framebuffer */ // Set up the new mode framebuffer
//current->flags = SDL_DOUBLEBUF |( flags & SDL_FULLSCREEN); current->flags = SDL_DOUBLEBUF |( flags & SDL_FULLSCREEN);
current->flags = flags & SDL_FULLSCREEN;
current->w = width; current->w = width;
current->h = height; current->h = height;
current->pitch = current->w * bytes_per_pixel; current->pitch = current->w * bytes_per_pixel;
current->pixels = this->hidden->back_buffer; current->pixels = this->hidden->buffer;
/* Set the hidden data */ /* Set the hidden data */
this->hidden->update_row = update_row; this->hidden->width = current->w;
this->hidden->magnification = mode->magnification; this->hidden->height = current->h;
this->hidden->pitch = current->pitch;
#if 0 draw_init(current);
// 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
/* We're done */ /* We're done */
return(current); return(current);
@ -347,197 +348,85 @@ static void WII_UnlockHWSurface(_THIS, SDL_Surface *surface)
return; return;
} }
static int WII_FlipHWSurface(_THIS, SDL_Surface *surface)
static void WII_FlipHWSurface(_THIS, SDL_Surface *surface)
{ {
Wii_Y1CBY2CR (*now)[][320] = 0; int h, w;
now = frame_buffer; long long int *dst = (long long int *) texturemem;
if (frame_buffer==frame_buffer1) { long long int *src1 = (long long int *) this->hidden->buffer;
frame_buffer = frame_buffer2; long long int *src2 = (long long int *) (this->hidden->buffer + this->hidden->pitch);
//this->hidden->back_buffer = frame_buffer1; long long int *src3 = (long long int *) (this->hidden->buffer + (this->hidden->pitch * 2));
//surface->pixels = frame_buffer1; long long int *src4 = (long long int *) (this->hidden->buffer + (this->hidden->pitch * 3));
} int rowpitch = (this->hidden->pitch >> 3) * 3;
else { int rowadjust = (this->hidden->pitch % 8) * 4;
frame_buffer = frame_buffer1; char *ra = NULL;
//this->hidden->back_buffer = frame_buffer2;
//surface->pixels = frame_buffer2; 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_Flush();
VIDEO_WaitVSync();
} return(1);
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;
}
}
} }
static void WII_UpdateRects(_THIS, int numrects, SDL_Rect *rects) 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) int WII_SetColors(_THIS, int first_color, int color_count, SDL_Color *colors)
{ {
const int last_color = first_color + color_count; return(0);
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);
} }
/* Note: If we are terminated, this could be called in the middle of
another SDL video routine -- notably UpdateRects.
*/
void WII_VideoQuit(_THIS) void WII_VideoQuit(_THIS)
{ {
/* if (this->screen->pixels != NULL) GX_AbortFrame();
{ GX_Flush();
SDL_free(this->screen->pixels);
this->screen->pixels = NULL; VIDEO_SetBlack(TRUE);
}*/ VIDEO_Flush();
} }
static void WII_DeleteDevice(SDL_VideoDevice *device) static void WII_DeleteDevice(SDL_VideoDevice *device)
@ -581,8 +470,7 @@ static SDL_VideoDevice *WII_CreateDevice(int devindex)
device->SetHWAlpha = NULL; device->SetHWAlpha = NULL;
device->LockHWSurface = WII_LockHWSurface; device->LockHWSurface = WII_LockHWSurface;
device->UnlockHWSurface = WII_UnlockHWSurface; device->UnlockHWSurface = WII_UnlockHWSurface;
//device->FlipHWSurface = WII_FlipHWSurface; device->FlipHWSurface = WII_FlipHWSurface;
device->FlipHWSurface = NULL;
device->FreeHWSurface = WII_FreeHWSurface; device->FreeHWSurface = WII_FreeHWSurface;
device->SetCaption = NULL; device->SetCaption = NULL;
device->SetIcon = NULL; device->SetIcon = NULL;

View file

@ -16,8 +16,7 @@
License along with this library; if not, write to the Free Software License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
Sam Lantinga Tantric, 2009
slouken@libsdl.org
*/ */
#include "SDL_config.h" #include "SDL_config.h"
@ -33,37 +32,15 @@
/* Hidden "this" pointer for the video functions */ /* Hidden "this" pointer for the video functions */
#define _THIS SDL_VideoDevice *this #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 */ /* Private display data */
struct SDL_PrivateVideoData struct SDL_PrivateVideoData
{ {
Uint8* back_buffer; Uint8* buffer;
Uint32* tmp_buffer; int width;
Wii_Palette palette; int height;
Wii_PackedPalette packed_palette; int pitch;
WII_UpdateRowFn* update_row;
unsigned int magnification;
}; };
/* Globals */ void WII_InitVideoSystem();
extern GXRModeObj* display_mode;
extern Wii_Y1CBY2CR (*frame_buffer)[][320];
extern Wii_Y1CBY2CR (*frame_buffer1)[][320];
extern Wii_Y1CBY2CR (*frame_buffer2)[][320];
#endif /* _SDL_wiivideo_h */ #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