From 7d71fbeea22e79560db7f09b5eb1c53aae5175a5 Mon Sep 17 00:00:00 2001 From: Andre Heider Date: Sun, 30 Aug 2009 17:01:03 +0000 Subject: Complete GFX rewrite with new features: - Standard and Dual-strike (240p) video modes, both with or without AA - Distinct textures for the overlay, game buffer and the cursor - Support for HW paletted textures - Less pixel buffer conversions - Cursor scaling - Support for kFeatureAspectRatioCorrection and kFeatureOverlaySupportsAlpha svn-id: r43830 --- backends/platform/wii/gfx.cpp | 611 +++++++++++++++++++++++++++++++ backends/platform/wii/gfx.h | 101 +++++ backends/platform/wii/gx_supp.cpp | 287 --------------- backends/platform/wii/gx_supp.h | 46 --- backends/platform/wii/main.cpp | 4 + backends/platform/wii/module.mk | 2 +- backends/platform/wii/osystem.cpp | 83 +++-- backends/platform/wii/osystem.h | 38 +- backends/platform/wii/osystem_events.cpp | 24 +- backends/platform/wii/osystem_gfx.cpp | 567 ++++++++++++++++------------ 10 files changed, 1141 insertions(+), 622 deletions(-) create mode 100644 backends/platform/wii/gfx.cpp create mode 100644 backends/platform/wii/gfx.h delete mode 100644 backends/platform/wii/gx_supp.cpp delete mode 100644 backends/platform/wii/gx_supp.h (limited to 'backends/platform/wii') diff --git a/backends/platform/wii/gfx.cpp b/backends/platform/wii/gfx.cpp new file mode 100644 index 0000000000..f34e2b1cca --- /dev/null +++ b/backends/platform/wii/gfx.cpp @@ -0,0 +1,611 @@ +/* + * Gamecube/Wii VIDEO/GX subsystem wrapper + * + * Copyright (C) 2008, 2009 Andre Heider "dhewg" + * + * This code is licensed to you under the terms of the GNU GPL, version 2; + * see file COPYING or http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt + * + */ + +#include +#include +#include +#include + +#include "gfx.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define FIFO_SIZE (256 * 1024) +#define ORIGIN_Z (-500) + +static GXRModeObj *_vm = NULL; +static bool _dualstrike = false; + +static u32 *_fb[2] = { NULL, NULL }; +static u8 _fb_active = 0; + +static u8 *_fifo = NULL; + +static u16 _underscan_x = 0; +static u16 _underscan_y = 0; +static f32 _ar = 4.0 / 3.0; +static bool _pillarboxing = false; +static Mtx _view; + +static struct { + guVector pos; + guVector up; + guVector view; +} _camera = { + { 0.0f, 0.0f, 0.0f }, + { 0.0f, 0.5f, 0.0f }, + { 0.0f, 0.0f, -0.5f } +}; + +// Standard, StandardAa, Ds, DsAa +static GXRModeObj *mode_table[5][4] = { + { &TVNtsc480Prog, &TVNtsc480ProgAa, &TVNtsc240Ds, &TVNtsc240DsAa }, + { &TVNtsc480IntDf, &TVNtsc480IntAa, &TVNtsc240Ds, &TVNtsc240DsAa }, + { &TVPal528IntDf, &TVPal524IntAa, &TVPal264Ds, &TVPal264DsAa }, + { &TVEurgb60Hz480IntDf, &TVEurgb60Hz480IntAa, &TVEurgb60Hz240Ds, &TVEurgb60Hz240DsAa }, + { &TVMpal480IntDf, &TVMpal480IntAa, &TVMpal240Ds, &TVMpal240DsAa } +}; + +static gfx_video_mode_t _gfx_video_get_mode(void) { + gfx_video_mode_t mode; + +#ifdef HW_RVL + if ((CONF_GetProgressiveScan() > 0) && VIDEO_HaveComponentCable()) { + mode = GFX_MODE_PROGRESSIVE; + } else { + switch (CONF_GetVideo()) { + case CONF_VIDEO_PAL: + if (CONF_GetEuRGB60() > 0) + mode = GFX_MODE_EURGB60; + else + mode = GFX_MODE_PAL; + break; + + case CONF_VIDEO_MPAL: + mode = GFX_MODE_MPAL; + break; + + default: + mode = GFX_MODE_NTSC; + break; + } + } +#else + switch (VIDEO_GetCurrentTvMode()) { + case VI_PAL: + mode = GFX_MODE_PAL; + break; + case VI_MPAL: + mode = GFX_MODE_MPAL; + break; + default: + mode = GFX_MODE_NTSC; + break; + } +#endif + + return mode; +} + +void gfx_video_init(gfx_video_mode_t mode, gfx_video_setup_t setup) { + u8 i; + + if (mode == GFX_MODE_AUTO) + mode = _gfx_video_get_mode(); + + _vm = mode_table[mode][setup]; + + _vm->viWidth = 672; + _vm->viXOrigin = (VI_MAX_WIDTH_NTSC - _vm->viWidth) / 2; + + if (_vm) + VIDEO_WaitVSync(); + + VIDEO_Configure(_vm); + + if (_fb[0]) + free(MEM_K1_TO_K0(_fb[0])); + if (_fb[1]) + free(MEM_K1_TO_K0(_fb[1])); + + _fb[0] = (u32 *) MEM_K0_TO_K1(SYS_AllocateFramebuffer(_vm)); + _fb[1] = (u32 *) MEM_K0_TO_K1(SYS_AllocateFramebuffer(_vm)); + + VIDEO_ClearFrameBuffer(_vm, _fb[0], COLOR_BLACK); + VIDEO_ClearFrameBuffer(_vm, _fb[1], COLOR_BLACK); + + VIDEO_SetNextFramebuffer(_fb[_fb_active]); + VIDEO_SetBlack(FALSE); + VIDEO_Flush(); + + for (i = 0; i < 4; ++i) + VIDEO_WaitVSync(); +} + +void gfx_video_deinit(void) { + u8 i; + + VIDEO_WaitVSync(); + VIDEO_SetBlack(TRUE); + VIDEO_SetNextFramebuffer(NULL); + VIDEO_Flush(); + + for (i = 0; i < 4; ++i) + VIDEO_WaitVSync(); + + if (_fb[0]) { + free(MEM_K1_TO_K0(_fb[0])); + _fb[0] = NULL; + } + + if (_fb[1]) { + free(MEM_K1_TO_K0(_fb[1])); + _fb[1] = NULL; + } +} + +u16 gfx_video_get_width(void) { + return _vm->fbWidth; +} + +u16 gfx_video_get_height(void) { + return _vm->efbHeight; +} + +static void _update_viewport(void) { + f32 ar; + u16 correction; + + u16 x1 = _underscan_x * 2; + u16 y1 = _underscan_y * 2; + u16 x2 = _vm->fbWidth - _underscan_x * 4; + u16 y2 = _vm->efbHeight - _underscan_y * 4; + + if (_pillarboxing) + ar = 16.0 / 9.0; + else + ar = 4.0 / 3.0; + + if (fabs(ar - _ar) > 0.01) { + if (ar > _ar) { + correction = _vm->viWidth - + (u16) round((f32) _vm->viWidth * _ar / ar); + + x1 += correction / 2; + x2 -= correction; + } else { + correction = _vm->efbHeight - + (u16) round((f32) _vm->efbHeight * ar / _ar); + + if (_dualstrike) + correction /= 2; + + y1 += correction / 2; + y2 -= correction; + } + } + + GX_SetViewport(x1, y1, x2, y2, 0, 1); + GX_SetScissor(x1, y1, x2, y2); +} + +void gfx_init(void) { + Mtx44 p; + GXColor bg = { 0, 0, 0, 0xff }; + f32 yscale; + u32 xfbHeight; + + GX_AbortFrame(); + + if (!_fifo) + _fifo = (u8 *) memalign(32, FIFO_SIZE); + + memset(_fifo, 0, FIFO_SIZE); + GX_Init(_fifo, FIFO_SIZE); + + GX_SetCopyClear(bg, 0x00ffffff); + + _update_viewport(); + + _dualstrike = _vm->viHeight == 2 * _vm->xfbHeight; + yscale = GX_GetYScaleFactor(_vm->efbHeight, _vm->xfbHeight); + xfbHeight = GX_SetDispCopyYScale(yscale); + GX_SetDispCopySrc(0, 0, _vm->fbWidth, _vm->efbHeight); + GX_SetDispCopyDst(_vm->fbWidth, xfbHeight); + GX_SetCopyFilter(_vm->aa, _vm->sample_pattern, GX_TRUE, _vm->vfilter); + GX_SetFieldMode(_vm->field_rendering, _dualstrike ? GX_ENABLE : GX_DISABLE); + + if (_vm->aa) + GX_SetPixelFmt(GX_PF_RGB565_Z16, GX_ZC_LINEAR); + else + GX_SetPixelFmt(GX_PF_RGB8_Z24, GX_ZC_LINEAR); + + GX_SetCullMode(GX_CULL_NONE); + GX_SetDispCopyGamma(GX_GM_1_0); + + GX_ClearVtxDesc(); + GX_SetVtxDesc(GX_VA_POS, GX_DIRECT); + GX_SetVtxDesc(GX_VA_CLR0, GX_DIRECT); + GX_SetVtxDesc(GX_VA_TEX0, GX_DIRECT); + + GX_SetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_POS_XYZ, GX_F32, 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_InvVtxCache(); + GX_InvalidateTexAll(); + + memset(&_view, 0, sizeof(Mtx)); + guLookAt(_view, &_camera.pos, &_camera.up, &_camera.view); + + guOrtho(p, 0, _vm->efbHeight, 0, _vm->fbWidth, 100, 1000); + GX_LoadProjectionMtx (p, GX_ORTHOGRAPHIC); + + GX_Flush(); +} + +void gfx_deinit(void) { + GX_AbortFrame(); + + free(_fifo); + _fifo = NULL; +} + +void gfx_set_underscan(u16 underscan_x, u16 underscan_y) { + _underscan_x = underscan_x; + _underscan_y = underscan_y; + + if (_underscan_x > 32) + _underscan_x = 32; + + if (_underscan_y > 32) + _underscan_y = 32; + + _update_viewport(); + GX_Flush(); +} + +void gfx_set_ar(f32 ar) { + _ar = ar; + + if (ar < 16.0 / 480.0) + ar = 16.0 / 480.0; + + if (ar > 640.0 / 16.0) + ar = 640.0 / 16.0; + + _update_viewport(); + GX_Flush(); +} + +void gfx_set_pillarboxing(bool enable) { + _pillarboxing = enable; + + _update_viewport(); + GX_Flush(); +} + +bool gfx_tex_init(gfx_tex_t *tex, gfx_tex_format_t format, u32 tlut_name, + u16 width, u16 height) { + u8 bpp; + u8 fmt_tex; + bool tlut; + u8 fmt_tlut; + u32 ax, ay; + u32 memsize; + + if (!tex) + return false; + + switch(format) { + case GFX_TF_RGB565: + bpp = 2; + fmt_tex = GX_TF_RGB565; + tlut = false; + fmt_tlut = 0; + ax = 3; + ay = 3; + break; + + case GFX_TF_RGB5A3: + bpp = 2; + fmt_tex = GX_TF_RGB5A3; + tlut = false; + fmt_tlut = 0; + ax = 3; + ay = 3; + break; + + case GFX_TF_PALETTE_RGB565: + bpp = 1; + fmt_tex = GX_TF_CI8; + tlut = true; + fmt_tlut = GX_TL_RGB565; + ax = 7; + ay = 3; + break; + + case GFX_TF_PALETTE_RGB5A3: + bpp = 1; + fmt_tex = GX_TF_CI8; + tlut = true; + fmt_tlut = GX_TL_RGB5A3; + ax = 7; + ay = 3; + break; + + default: + gfx_tex_deinit(tex); + return false; + } + + if ((width & ax) || (height & ay)) { + gfx_tex_deinit(tex); + return false; + } + + if (tlut) { + if (!tex->palette) { + tex->palette = (u16 *) memalign(32, 256 * 2); + if (!tex->palette) { + gfx_tex_deinit(tex); + return false; + } + + memset(tex->palette, 0, 256 * 2); + DCFlushRange(tex->palette, 256 * 2); + } + + tex->tlut_name = tlut_name; + GX_InitTlutObj(&tex->tlut, tex->palette, fmt_tlut, 256); + } else { + tex->tlut_name = 0; + free(tex->palette); + tex->palette = NULL; + } + + if (!tex->pixels || (width != tex->width) || (height != tex->height || + bpp != tex->bpp)) { + free(tex->pixels); + + memsize = width * height * bpp; + tex->pixels = memalign(32, memsize); + + if (!tex->pixels) { + gfx_tex_deinit(tex); + return false; + } + + memset(tex->pixels, 0, memsize); + DCFlushRange(tex->pixels, memsize); + } + + tex->format = format; + tex->width = width; + tex->height = height; + tex->bpp = bpp; + + if (tlut) { + GX_LoadTlut(&tex->tlut, tlut_name); + GX_InitTexObjCI(&tex->obj, tex->pixels, width, height, fmt_tex, + GX_CLAMP, GX_CLAMP, GX_FALSE, tlut_name); + } else { + GX_InitTexObj(&tex->obj, tex->pixels, width, height, fmt_tex, + GX_CLAMP, GX_CLAMP, GX_FALSE); + } + + return true; +} + +void gfx_tex_deinit(gfx_tex_t *tex) { + if (!tex) + return; + + free(tex->pixels); + free(tex->palette); + memset(tex, 0, sizeof(gfx_tex_t)); +} + +void gfx_coords(gfx_coords_t *coords, gfx_tex_t *tex, gfx_coord_t type) { + if (!coords || !tex) + return; + + switch(type) { + case GFX_COORD_FULLSCREEN: + coords->x = 0.0; + coords->y = 0.0; + coords->w = _vm->fbWidth; + coords->h = _vm->efbHeight; + break; + + case GFX_COORD_CENTER: + coords->x = (_vm->fbWidth - tex->width) / 2; + coords->y = (_vm->efbHeight - tex->height) / 2; + coords->w = tex->width; + coords->h = tex->height; + break; + + default: + break; + } +} + +bool gfx_tex_flush_texture(gfx_tex_t *tex) { + if (!tex) + return false; + + DCFlushRange(tex->pixels, tex->width * tex->height * tex->bpp); + return true; +} + +bool gfx_tex_flush_palette(gfx_tex_t *tex) { + if (!tex || !tex->palette) + return false; + + DCFlushRange(tex->palette, 256 * 2); + GX_LoadTlut(&tex->tlut, tex->tlut_name); + + return true; +} + +bool gfx_tex_clear_palette(gfx_tex_t *tex) { + if (!tex || !tex->palette) + return false; + + memset(tex->palette, 0, 256 * 2); + DCFlushRange(tex->palette, 256 * 2); + GX_LoadTlut(&tex->tlut, tex->tlut_name); + + return true; +} + +bool gfx_tex_convert(gfx_tex_t *tex, const void *src) { + bool ret; + u16 w, h, x, y; + u64 *dst, *src1, *src2, *src3, *src4; + u16 rowpitch; + u16 pitch; + const u8 *s = (const u8 *) src; + + if (!tex) + return false; + + ret = false; + w = tex->width; + h = tex->height; + + switch(tex->format) { + case GFX_TF_RGB565: + case GFX_TF_RGB5A3: + pitch = w * 2; + dst = (u64 *) tex->pixels; + src1 = (u64 *) s; + src2 = (u64 *) (s + pitch); + src3 = (u64 *) (s + (pitch * 2)); + src4 = (u64 *) (s + (pitch * 3)); + rowpitch = (pitch >> 3) * 3 + pitch % 8; + + for (y = 0; y < h; y += 4) { + for (x = 0; x < (w >> 2); x++) { + *dst++ = *src1++; + *dst++ = *src2++; + *dst++ = *src3++; + *dst++ = *src4++; + } + + src1 += rowpitch; + src2 += rowpitch; + src3 += rowpitch; + src4 += rowpitch; + } + + ret = true; + break; + + case GFX_TF_PALETTE_RGB565: + case GFX_TF_PALETTE_RGB5A3: + pitch = w; + dst = (u64 *) tex->pixels; + src1 = (u64 *) s; + src2 = (u64 *) (s + pitch); + src3 = (u64 *) (s + (pitch * 2)); + src4 = (u64 *) (s + (pitch * 3)); + rowpitch = (pitch >> 3) * 3 + pitch % 8; + + for (y = 0; y < h; y += 4) { + for (x = 0; x < (w >> 3); x++) { + *dst++ = *src1++; + *dst++ = *src2++; + *dst++ = *src3++; + *dst++ = *src4++; + } + + src1 += rowpitch; + src2 += rowpitch; + src3 += rowpitch; + src4 += rowpitch; + } + + ret = true; + break; + + default: + break; + } + + if (ret) + DCFlushRange(tex->pixels, w * h * tex->bpp); + + return ret; +} + +void gfx_frame_start(void) { + GX_InvVtxCache(); + GX_InvalidateTexAll(); + + GX_SetNumChans(1); + GX_SetNumTexGens(1); + 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_COLOR0A0); + + GX_SetBlendMode(GX_BM_BLEND, GX_BL_SRCALPHA, GX_BL_INVSRCALPHA, GX_LO_NOOP); +} + +void gfx_frame_end(void) { + GX_SetZMode(GX_TRUE, GX_LEQUAL, GX_TRUE); + GX_SetColorUpdate(GX_TRUE); + + GX_CopyDisp(_fb[_fb_active], GX_TRUE); + GX_Flush(); + GX_DrawDone(); + + VIDEO_SetNextFramebuffer(_fb[_fb_active]); + VIDEO_Flush(); + VIDEO_WaitVSync(); + + _fb_active ^= 1; +} + +static void _tex_vert(f32 x, f32 y, f32 z, f32 s, f32 t, u32 c) { + GX_Position3f32(x, y, z); + GX_Color1u32(c); + GX_TexCoord2f32(s, t); +} + +void gfx_draw_tex(gfx_tex_t *tex, gfx_coords_t *coords) { + Mtx m; + Mtx mv; + + if (!tex || !coords) + return; + + GX_LoadTexObj(&tex->obj, GX_TEXMAP0); + + guMtxIdentity(m); + guMtxTrans(m, coords->x, coords->y, ORIGIN_Z); + guMtxConcat(_view, m, mv); + GX_LoadPosMtxImm(mv, GX_PNMTX0); + + GX_Begin(GX_QUADS, GX_VTXFMT0, 4); + _tex_vert(0.0, 0.0, 0.0, 0.0, 0.0, 0xffffffff); + _tex_vert(coords->w, 0.0, 0.0, 1.0, 0.0, 0xffffffff); + _tex_vert(coords->w, coords->h, 0.0, 1.0, 1.0, 0xffffffff); + _tex_vert(0.0, coords->h, 0.0, 0.0, 1.0, 0xffffffff); + GX_End(); +} + +#ifdef __cplusplus +} +#endif + diff --git a/backends/platform/wii/gfx.h b/backends/platform/wii/gfx.h new file mode 100644 index 0000000000..f4c49653c5 --- /dev/null +++ b/backends/platform/wii/gfx.h @@ -0,0 +1,101 @@ +/* + * Gamecube/Wii VIDEO/GX subsystem wrapper + * + * Copyright (C) 2008, 2009 Andre Heider "dhewg" + * + * This code is licensed to you under the terms of the GNU GPL, version 2; + * see file COPYING or http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt + * + */ + +#ifndef __GFX_H__ +#define __GFX_H__ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum { + GFX_MODE_AUTO = -1, + GFX_MODE_PROGRESSIVE = 0, + GFX_MODE_NTSC, + GFX_MODE_PAL, + GFX_MODE_EURGB60, + GFX_MODE_MPAL +} gfx_video_mode_t; + +typedef enum { + GFX_SETUP_STANDARD = 0, + GFX_SETUP_STANDARD_AA, + GFX_SETUP_DS, + GFX_SETUP_DS_AA +} gfx_video_setup_t; + +typedef enum { + GFX_TF_RGB565 = 0, + GFX_TF_RGB5A3, + GFX_TF_PALETTE_RGB565, + GFX_TF_PALETTE_RGB5A3 +} gfx_tex_format_t; + +typedef struct { + void *pixels; + u16 *palette; + + gfx_tex_format_t format; + u16 width; + u16 height; + u8 bpp; + GXTexObj obj; + GXTlutObj tlut; + u32 tlut_name; +} gfx_tex_t; + +typedef enum { + GFX_COORD_FULLSCREEN = 0, + GFX_COORD_CENTER +} gfx_coord_t; + +typedef struct { + f32 x, y; + f32 w, h; +} gfx_coords_t; + +void gfx_video_init(gfx_video_mode_t mode, gfx_video_setup_t setup); +void gfx_video_deinit(void); + +u16 gfx_video_get_width(void); +u16 gfx_video_get_height(void); + +void gfx_init(void); +void gfx_deinit(void); + +void gfx_set_underscan(u16 underscan_x, u16 underscan_y); +void gfx_set_ar(f32 ar); +void gfx_set_pillarboxing(bool enable); + +bool gfx_tex_init(gfx_tex_t *tex, gfx_tex_format_t format, u32 tlut_name, + u16 width, u16 height); +void gfx_tex_deinit(gfx_tex_t *tex); + +void gfx_coords(gfx_coords_t *coords, gfx_tex_t *tex, gfx_coord_t type); + +bool gfx_tex_flush_texture(gfx_tex_t *tex); +bool gfx_tex_flush_palette(gfx_tex_t *tex); +bool gfx_tex_clear_palette(gfx_tex_t *tex); + +bool gfx_tex_convert(gfx_tex_t *tex, const void *src); + +void gfx_frame_start(void); +void gfx_frame_end(void); + +void gfx_draw_tex(gfx_tex_t *tex, gfx_coords_t *coords); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/backends/platform/wii/gx_supp.cpp b/backends/platform/wii/gx_supp.cpp deleted file mode 100644 index f33adae566..0000000000 --- a/backends/platform/wii/gx_supp.cpp +++ /dev/null @@ -1,287 +0,0 @@ -/**************************************************************************** -* Generic GX Support for Emulators -* softdev 2007 -* dhewg 2008 -* -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program 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 General Public License for more details. -* -* You should have received a copy of the GNU General Public License along -* with this program; if not, write to the Free Software Foundation, Inc., -* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -* -* NGC GX Video Functions -* -* These are pretty standard functions to setup and use GX scaling. -****************************************************************************/ - -#include -#include -#include -#include - -#include "gx_supp.h" - -#define DEFAULT_FIFO_SIZE (256 * 1024) - -#define HASPECT 320 -#define VASPECT 240 - -#ifdef __cplusplus -extern "C" { -#endif - -/*** 2D ***/ -static u32 whichfb; -static u32 *xfb[2]; -GXRModeObj *vmode = NULL; - -/*** 3D GX ***/ -static u8 *gp_fifo; - -/*** Texture memory ***/ -static u8 *texturemem = NULL; -static u32 texturesize; - -static GXTexObj texobj; -static Mtx view; -static u16 vwidth, vheight, oldvwidth, oldvheight; -static float tex_xT = 0.0f, tex_yT = 0.0f; - -/* New texture based scaler */ -typedef struct tagcamera { - guVector pos; - guVector up; - guVector view; -} camera; - -static s16 square[] ATTRIBUTE_ALIGN(32) = { - -HASPECT, VASPECT, 0, - HASPECT, VASPECT, 0, - HASPECT, -VASPECT, 0, - -HASPECT, -VASPECT, 0, -}; - -static camera cam = { - { 0.0f, 0.0f, 370.0f }, - { 0.0f, 0.5f, 0.0f }, - { 0.0f, 0.0f, -0.5f } -}; - -void GX_InitVideo() { - vmode = VIDEO_GetPreferredMode(NULL); - - vmode->viWidth = 688; - vmode->viXOrigin = (VI_MAX_WIDTH_PAL - 688) / 2; - - VIDEO_Configure(vmode); - - xfb[0] = (u32 *) MEM_K0_TO_K1 (SYS_AllocateFramebuffer(vmode)); - xfb[1] = (u32 *) MEM_K0_TO_K1 (SYS_AllocateFramebuffer(vmode)); - gp_fifo = (u8 *) memalign(32, DEFAULT_FIFO_SIZE); - - VIDEO_ClearFrameBuffer(vmode, xfb[0], COLOR_BLACK); - VIDEO_ClearFrameBuffer(vmode, xfb[1], COLOR_BLACK); - - whichfb = 0; - VIDEO_SetNextFramebuffer(xfb[whichfb]); - VIDEO_SetBlack(FALSE); - VIDEO_Flush(); - VIDEO_WaitVSync(); - - if (vmode->viTVMode & VI_NON_INTERLACE) - VIDEO_WaitVSync(); -} - -void GX_SetTexTrans(float xT, float yT) { - tex_xT = xT; - tex_yT = yT; -} - -void GX_SetCamPosZ(float f) { - cam.pos.z = f; -} - -/**************************************************************************** - * Scaler Support Functions - ****************************************************************************/ -static void draw_init(void) { - 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_SetTexCoordGen(GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_TEX0, GX_IDENTITY); - - GX_InvalidateTexAll(); - - GX_InitTexObj(&texobj, texturemem, vwidth, vheight, GX_TF_RGB565, - GX_CLAMP, GX_CLAMP, GX_FALSE); -} - -static void draw_vert(u8 pos, u8 c, f32 s, f32 t) { - GX_Position1x8(pos); - GX_Color1x8(c); - GX_TexCoord2f32(s, t); -} - -static void draw_square(Mtx v) { - Mtx m; - Mtx mv; - - guMtxIdentity(m); - guMtxTransApply(m, m, tex_xT, tex_yT, -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(); -} - -/**************************************************************************** - * StartGX - ****************************************************************************/ -void GX_Start(u16 width, u16 height, s16 haspect, s16 vaspect) { - static bool inited = false; - Mtx p; - GXColor gxbackground = { 0, 0, 0, 0xff }; - - /*** Set new aspect ***/ - square[0] = square[9] = -haspect; - square[3] = square[6] = haspect; - square[1] = square[4] = vaspect; - square[7] = square[10] = -vaspect; - - /*** Allocate 32byte aligned texture memory ***/ - texturesize = (width * height) * 2; - - if (texturemem) - free(texturemem); - - texturemem = (u8 *) memalign(32, texturesize); - memset(texturemem, 0, texturesize); - - /*** Setup for first call to scaler ***/ - oldvwidth = oldvheight = 0; - - if (inited) - return; - - inited = true; - - /*** Clear out FIFO area ***/ - memset(gp_fifo, 0, DEFAULT_FIFO_SIZE); - - /*** Initialise GX ***/ - GX_Init(gp_fifo, DEFAULT_FIFO_SIZE); - GX_SetCopyClear(gxbackground, 0x00ffffff); - - 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)); - GX_SetPixelFmt(GX_PF_RGB8_Z24, GX_ZC_LINEAR); - GX_SetCullMode(GX_CULL_NONE); - GX_CopyDisp(xfb[whichfb ^ 1], GX_TRUE); - GX_SetDispCopyGamma(GX_GM_1_0); - - guPerspective(p, 60, 1.33f, 10.0f, 1000.0f); - GX_LoadProjectionMtx(p, GX_PERSPECTIVE); - - GX_Flush(); -} - -/**************************************************************************** -* GX_Render -* -* Pass in a buffer, width and height to update as a tiled RGB565 texture -****************************************************************************/ -void GX_Render(u16 width, u16 height, u8 *buffer, u16 pitch) { - u16 h, w; - u64 *dst = (u64 *) texturemem; - u64 *src1 = (u64 *) buffer; - u64 *src2 = (u64 *) (buffer + pitch); - u64 *src3 = (u64 *) (buffer + (pitch * 2)); - u64 *src4 = (u64 *) (buffer + (pitch * 3)); - u16 rowpitch = (pitch >> 3) * 3 + pitch % 8; - - vwidth = width; - vheight = height; - - whichfb ^= 1; - - if ((oldvheight != vheight) || (oldvwidth != vwidth)) { - /** Update scaling **/ - oldvwidth = vwidth; - oldvheight = vheight; - draw_init(); - memset(&view, 0, sizeof(Mtx)); - guLookAt(view, &cam.pos, &cam.up, &cam.view); - GX_SetViewport(0, 0, vmode->fbWidth, vmode->efbHeight, 0, 1); - } - - GX_InvVtxCache(); - GX_InvalidateTexAll(); - GX_SetTevOp(GX_TEVSTAGE0, GX_DECAL); - GX_SetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR0A0); - - for (h = 0; h < vheight; h += 4) { - for (w = 0; w < (vwidth >> 2); w++) { - *dst++ = *src1++; - *dst++ = *src2++; - *dst++ = *src3++; - *dst++ = *src4++; - } - - src1 += rowpitch; - src2 += rowpitch; - src3 += rowpitch; - src4 += rowpitch; - } - - DCFlushRange(texturemem, texturesize); - - GX_SetNumChans(1); - GX_LoadTexObj(&texobj, GX_TEXMAP0); - - draw_square(view); - - GX_DrawDone(); - - GX_SetZMode(GX_TRUE, GX_LEQUAL, GX_TRUE); - GX_SetColorUpdate(GX_TRUE); - GX_CopyDisp(xfb[whichfb], GX_TRUE); - GX_Flush(); - - VIDEO_SetNextFramebuffer(xfb[whichfb]); - VIDEO_Flush(); -} - -#ifdef __cplusplus -} -#endif - diff --git a/backends/platform/wii/gx_supp.h b/backends/platform/wii/gx_supp.h deleted file mode 100644 index 3433ef8df5..0000000000 --- a/backends/platform/wii/gx_supp.h +++ /dev/null @@ -1,46 +0,0 @@ -/**************************************************************************** -* Generic GX Scaler -* softdev 2007 -* dhewg 2008 -* -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program 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 General Public License for more details. -* -* You should have received a copy of the GNU General Public License along -* with this program; if not, write to the Free Software Foundation, Inc., -* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -* -* NGC GX Video Functions -* -* These are pretty standard functions to setup and use GX scaling. -****************************************************************************/ -#ifndef _WII_GX_SUPP_H_ -#define _WII_GX_SUPP_H_ - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -extern GXRModeObj *vmode; - -void GX_InitVideo(); -void GX_SetTexTrans(float xT, float yT); -void GX_SetCamPosZ(float f); - -void GX_Start(u16 width, u16 height, s16 haspect, s16 vaspect); -void GX_Render(u16 width, u16 height, u8 *buffer, u16 pitch); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/backends/platform/wii/main.cpp b/backends/platform/wii/main.cpp index c714a2a10e..801778395f 100644 --- a/backends/platform/wii/main.cpp +++ b/backends/platform/wii/main.cpp @@ -37,6 +37,8 @@ #include #endif +#include "gfx.h" + #ifdef __cplusplus extern "C" { #endif @@ -153,6 +155,8 @@ int main(int argc, char *argv[]) { printf("reloading\n"); + gfx_video_deinit(); + return res; } diff --git a/backends/platform/wii/module.mk b/backends/platform/wii/module.mk index 912389902b..7a4d08b375 100644 --- a/backends/platform/wii/module.mk +++ b/backends/platform/wii/module.mk @@ -2,7 +2,7 @@ MODULE := backends/platform/wii MODULE_OBJS := \ main.o \ - gx_supp.o \ + gfx.o \ osystem.o \ osystem_gfx.o \ osystem_sfx.o \ diff --git a/backends/platform/wii/osystem.cpp b/backends/platform/wii/osystem.cpp index 3f53605e85..50016db932 100644 --- a/backends/platform/wii/osystem.cpp +++ b/backends/platform/wii/osystem.cpp @@ -19,8 +19,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -#include "backends/fs/wii/wii-fs-factory.h" #include "common/config-manager.h" +#include "backends/fs/wii/wii-fs-factory.h" #include "osystem.h" @@ -32,68 +32,70 @@ OSystem_Wii::OSystem_Wii() : _startup_time(0), - _palette(NULL), - _cursorPalette(NULL), + _cursorScale(1), _cursorPaletteDisabled(true), + _cursorPalette(NULL), + _cursorPaletteDirty(false), + _gameRunning(false), _gameWidth(0), _gameHeight(0), _gamePixels(NULL), + _gameDirty(false), - _overlayVisible(false), + _overlayVisible(true), _overlayWidth(0), _overlayHeight(0), _overlaySize(0), _overlayPixels(NULL), + _overlayDirty(false), _lastScreenUpdate(0), - _texture(NULL), _currentWidth(0), _currentHeight(0), + _currentXScale(1), + _currentYScale(1), - _activeGraphicsMode(0), + _configGraphicsMode(0), + _actualGraphicsMode(0), #ifdef USE_RGB_COLOR - _texturePF(Graphics::PixelFormat(2, 5, 6, 5, 0, 11, 5, 0, 0)), - _screenPF(Graphics::PixelFormat::createFormatCLUT8()), - _cursorPF(Graphics::PixelFormat::createFormatCLUT8()), + _pfRGB565(Graphics::PixelFormat(2, 5, 6, 5, 0, 11, 5, 0, 0)), + _pfRGB3444(Graphics::PixelFormat(2, 4, 4, 4, 3, 8, 4, 0, 12)), + _pfGame(Graphics::PixelFormat::createFormatCLUT8()), + _pfGameTexture(Graphics::PixelFormat::createFormatCLUT8()), + _pfCursor(Graphics::PixelFormat::createFormatCLUT8()), #endif _fullscreen(false), + _arCorrection(false), _mouseVisible(false), _mouseX(0), _mouseY(0), - _mouseWidth(0), - _mouseHeight(0), _mouseHotspotX(0), _mouseHotspotY(0), _mouseKeyColor(0), - _mouseCursor(NULL), _kbd_active(false), _event_quit(false), + _lastPadCheck(0), + _savefile(NULL), _mixer(NULL), _timer(NULL) { } OSystem_Wii::~OSystem_Wii() { - if (_savefile) { - delete _savefile; - _savefile = NULL; - } + delete _savefile; + _savefile = NULL; - if (_mixer) { - delete _mixer; - _mixer = NULL; - } + delete _mixer; + _mixer = NULL; - if (_timer) { - delete _timer; - _timer = NULL; - } + delete _timer; + _timer = NULL; } void OSystem_Wii::initBackend() { @@ -107,12 +109,13 @@ void OSystem_Wii::initBackend() { _mixer = new Audio::MixerImpl(this); _timer = new DefaultTimerManager(); - _fullscreen = ConfMan.getBool("fullscreen"); - initGfx(); initSfx(); initEvents(); + ConfMan.registerDefault("fullscreen", true); + ConfMan.registerDefault("aspect_ratio", true); + OSystem::initBackend(); } @@ -125,16 +128,33 @@ void OSystem_Wii::quit() { WiiFilesystemFactory::asyncHandler(false, NULL); } +void OSystem_Wii::engineInit() { + _gameRunning = true; + // umount not required filesystems for this game + WiiFilesystemFactory::asyncHandler(false, &ConfMan.get("path")); +} + +void OSystem_Wii::engineDone() { + _gameRunning = false; + switchVideoMode(GFX_SETUP_STANDARD); + gfx_set_ar(4.0 / 3.0); +} + bool OSystem_Wii::hasFeature(Feature f) { return (f == kFeatureFullscreenMode) || - (f == kFeatureCursorHasPalette); + (f == kFeatureAspectRatioCorrection) || + (f == kFeatureCursorHasPalette) || + (f == kFeatureOverlaySupportsAlpha); } void OSystem_Wii::setFeatureState(Feature f, bool enable) { switch (f) { case kFeatureFullscreenMode: _fullscreen = enable; - setGraphicsMode(_activeGraphicsMode); + gfx_set_pillarboxing(!enable); + break; + case kFeatureAspectRatioCorrection: + _arCorrection = enable; break; default: break; @@ -145,6 +165,8 @@ bool OSystem_Wii::getFeatureState(Feature f) { switch (f) { case kFeatureFullscreenMode: return _fullscreen; + case kFeatureAspectRatioCorrection: + return _arCorrection; default: return false; } @@ -220,8 +242,3 @@ void OSystem_Wii::getTimeAndDate(struct tm &t) const { t = *localtime(&curTime); } -void OSystem_Wii::engineInit() { - // umount not required filesystems for this game - WiiFilesystemFactory::asyncHandler(false, &ConfMan.get("path")); -} - diff --git a/backends/platform/wii/osystem.h b/backends/platform/wii/osystem.h index 72263af5a8..8f8547c1dd 100644 --- a/backends/platform/wii/osystem.h +++ b/backends/platform/wii/osystem.h @@ -26,7 +26,6 @@ #include "common/fs.h" #include "common/rect.h" #include "common/events.h" - #include "backends/base-backend.h" #include "backends/saves/default/default-saves.h" #include "backends/timer/default/default-timer.h" @@ -34,6 +33,8 @@ #include "graphics/surface.h" #include "sound/mixer_intern.h" +#include "gfx.h" + #include #include #include @@ -57,38 +58,49 @@ class OSystem_Wii : public BaseBackend { private: s64 _startup_time; - u16 *_palette; - u16 *_cursorPalette; + int _cursorScale; bool _cursorPaletteDisabled; + u16 *_cursorPalette; + bool _cursorPaletteDirty; + bool _gameRunning; u16 _gameWidth, _gameHeight; u8 *_gamePixels; Graphics::Surface _surface; + gfx_coords_t _coordsGame; + gfx_tex_t _texGame; + bool _gameDirty; bool _overlayVisible; u16 _overlayWidth, _overlayHeight; u32 _overlaySize; OverlayColor *_overlayPixels; + gfx_coords_t _coordsOverlay; + gfx_tex_t _texOverlay; + bool _overlayDirty; u32 _lastScreenUpdate; - u16 *_texture; u16 _currentWidth, _currentHeight; + f32 _currentXScale, _currentYScale; - s32 _activeGraphicsMode; + s32 _configGraphicsMode; + s32 _actualGraphicsMode; #ifdef USE_RGB_COLOR - const Graphics::PixelFormat _texturePF; - Graphics::PixelFormat _screenPF; - Graphics::PixelFormat _cursorPF; + const Graphics::PixelFormat _pfRGB565; + const Graphics::PixelFormat _pfRGB3444; + Graphics::PixelFormat _pfGame; + Graphics::PixelFormat _pfGameTexture; + Graphics::PixelFormat _pfCursor; #endif bool _fullscreen; + bool _arCorrection; bool _mouseVisible; s32 _mouseX, _mouseY; - u32 _mouseWidth, _mouseHeight; s32 _mouseHotspotX, _mouseHotspotY; u16 _mouseKeyColor; - u8 *_mouseCursor; + gfx_tex_t _texMouse; bool _kbd_active; @@ -98,6 +110,8 @@ private: void initGfx(); void deinitGfx(); + void updateScreenResolution(); + void switchVideoMode(int mode); void initSfx(); void deinitSfx(); @@ -117,6 +131,8 @@ public: virtual ~OSystem_Wii(); virtual void initBackend(); + virtual void engineInit(); + virtual void engineDone(); virtual bool hasFeature(Feature f); virtual void setFeatureState(Feature f, bool enable); @@ -182,8 +198,6 @@ public: virtual Common::TimerManager *getTimerManager(); virtual FilesystemFactory *getFilesystemFactory(); virtual void getTimeAndDate(struct tm &t) const; - - virtual void engineInit(); }; #endif diff --git a/backends/platform/wii/osystem_events.cpp b/backends/platform/wii/osystem_events.cpp index 0967db1625..e8b25b3e7f 100644 --- a/backends/platform/wii/osystem_events.cpp +++ b/backends/platform/wii/osystem_events.cpp @@ -43,6 +43,7 @@ #define PADS_B (PAD_BUTTON_B | (WPAD_BUTTON_B << 16)) #define PADS_X (PAD_BUTTON_X | (WPAD_BUTTON_MINUS << 16)) #define PADS_Y (PAD_BUTTON_Y | (WPAD_BUTTON_PLUS << 16)) +#define PADS_R (PAD_TRIGGER_R | (WPAD_BUTTON_1 << 16)) #define PADS_Z (PAD_TRIGGER_Z | (WPAD_BUTTON_2 << 16)) #define PADS_START (PAD_BUTTON_START | (WPAD_BUTTON_HOME << 16)) #define PADS_UP (PAD_BUTTON_UP | (WPAD_BUTTON_UP << 16)) @@ -54,6 +55,7 @@ #define PADS_B PAD_BUTTON_B #define PADS_X PAD_BUTTON_X #define PADS_Y PAD_BUTTON_Y +#define PADS_R PAD_TRIGGER_R #define PADS_Z PAD_TRIGGER_Z #define PADS_START PAD_BUTTON_START #define PADS_UP PAD_BUTTON_UP @@ -308,7 +310,6 @@ bool OSystem_Wii::pollEvent(Common::Event &event) { s32 res = WPAD_Probe(0, NULL); if (res == WPAD_ERR_NONE) { - bd |= WPAD_ButtonsDown(0) << 16; bh |= WPAD_ButtonsHeld(0) << 16; bu |= WPAD_ButtonsUp(0) << 16; @@ -318,6 +319,27 @@ bool OSystem_Wii::pollEvent(Common::Event &event) { if (bd || bu) { byte flags = 0; + // TODO: add this to an option dialog + if (bh & PADS_R) { + static u16 vpo_x = 0; + static u16 vpo_y = 0; + + if (bd & PADS_LEFT) + vpo_x = (vpo_x - 1) % 32; + + if (bd & PADS_RIGHT) + vpo_x = (vpo_x + 1) % 32; + + if (bd & PADS_UP) + vpo_y = (vpo_y - 1) % 32; + + if (bd & PADS_DOWN) + vpo_y = (vpo_y + 1) % 32; + + gfx_set_underscan(vpo_x, vpo_y); + return false; + } + if (bh & PADS_UP) { PAD_EVENT(PADS_START, Common::KEYCODE_F5, Common::ASCII_F5, Common::KBD_CTRL); diff --git a/backends/platform/wii/osystem_gfx.cpp b/backends/platform/wii/osystem_gfx.cpp index b0e3f112c1..6f9e8a04e8 100644 --- a/backends/platform/wii/osystem_gfx.cpp +++ b/backends/platform/wii/osystem_gfx.cpp @@ -21,43 +21,32 @@ #include +#include "common/config-manager.h" #include "graphics/conversion.h" +#include "backends/fs/wii/wii-fs-factory.h" #include "osystem.h" -#include "gx_supp.h" +#include "gfx.h" +#define ROUNDUP(x,n) (-(-(x) & -(n))) #define MAX_FPS 30 - -enum GraphicModeID { - GM_DEFAULT = 0, - GM_OVERSCAN1, - GM_OVERSCAN2, - GM_OVERSCAN3, - GM_OVERSCAN4, - GM_OVERSCAN5 -}; +#define TLUT_GAME GX_TLUT0 +#define TLUT_MOUSE GX_TLUT1 static const OSystem::GraphicsMode s_supportedGraphicsModes[] = { - { "standard", "Standard", GM_DEFAULT }, - { "overscan1", "Overscan 1", GM_OVERSCAN1 }, - { "overscan2", "Overscan 2", GM_OVERSCAN2 }, - { "overscan3", "Overscan 3", GM_OVERSCAN3 }, - { "overscan4", "Overscan 4", GM_OVERSCAN4 }, - { "overscan5", "Overscan 5", GM_OVERSCAN5 }, + { "standard", "Standard", GFX_SETUP_STANDARD }, + { "standardaa", "Standard antialiased", GFX_SETUP_STANDARD_AA }, + { "ds", "Double-strike", GFX_SETUP_DS }, + { "dsaa", "Double-strike antialiased", GFX_SETUP_DS_AA }, { 0, 0, 0 } }; void OSystem_Wii::initGfx() { - _surface.w = 0; - _surface.h = 0; - _surface.pitch = 0; - _surface.pixels = NULL; - _surface.bytesPerPixel = 0; - - GX_InitVideo(); + gfx_video_init(GFX_MODE_AUTO, GFX_SETUP_STANDARD); + gfx_init(); - _overlayWidth = 640; - _overlayHeight = 480; + _overlayWidth = gfx_video_get_width(); + _overlayHeight = gfx_video_get_height(); #ifndef GAMECUBE if (CONF_GetAspectRatio() && _fullscreen) @@ -67,49 +56,89 @@ void OSystem_Wii::initGfx() { _overlaySize = _overlayWidth * _overlayHeight * 2; _overlayPixels = (OverlayColor *) memalign(32, _overlaySize); - _palette = (u16 *) memalign(32, 256 * 2); - memset(_palette, 0, 256 * 2); + memset(&_texMouse, 0, sizeof(gfx_tex_t)); + memset(&_texOverlay, 0, sizeof(gfx_tex_t)); + memset(&_texGame, 0, sizeof(gfx_tex_t)); + + _cursorPalette = (u16 *) malloc(256 * 2); + if (!_cursorPalette) { + printf("could not alloc palette buffer\n"); + ::abort(); + } - _cursorPalette = (u16 *) memalign(32, 256 * 2); memset(_cursorPalette, 0, 256 * 2); - _texture = (u16 *) memalign(32, 640 * 480 * 2); + if (!gfx_tex_init(&_texOverlay, GFX_TF_RGB5A3, 0, + _overlayWidth, _overlayHeight)) { + printf("could not init the overlay texture\n"); + ::abort(); + } - setGraphicsMode(_activeGraphicsMode); + gfx_coords(&_coordsOverlay, &_texOverlay, GFX_COORD_FULLSCREEN); } void OSystem_Wii::deinitGfx() { - GX_AbortFrame(); + gfx_deinit(); - if (_gamePixels) { - free(_gamePixels); - _gamePixels = NULL; - } + gfx_tex_deinit(&_texMouse); + gfx_tex_deinit(&_texGame); + gfx_tex_deinit(&_texOverlay); - if (_palette) { - free(_palette); - _palette = NULL; - } + free(_cursorPalette); + _cursorPalette = NULL; - if (_overlayPixels) { - free(_overlayPixels); - _overlayPixels = NULL; - } + free(_gamePixels); + _gamePixels = NULL; - if (_mouseCursor) { - free(_mouseCursor); - _mouseCursor = NULL; - } + free(_overlayPixels); + _overlayPixels = NULL; +} - if (_cursorPalette) { - free(_cursorPalette); - _cursorPalette = NULL; +void OSystem_Wii::updateScreenResolution() { + if (_overlayVisible) { + _currentWidth = _overlayWidth; + _currentHeight = _overlayHeight; + } else { + _currentWidth = _gameWidth; + _currentHeight = _gameHeight; } - if (_texture) { - free(_texture); - _texture = NULL; + if (_currentWidth > 0) + _currentXScale = f32(gfx_video_get_width()) / f32(_currentWidth); + else + _currentXScale = 1.0; + + if (_currentHeight > 0) + _currentYScale = f32(gfx_video_get_height()) / f32(_currentHeight); + else + _currentYScale = 1.0; + + updateEventScreenResolution(); +} + +void OSystem_Wii::switchVideoMode(int mode) { + if (_gameHeight > 240) { + if (mode == GFX_SETUP_DS) + mode = GFX_SETUP_STANDARD; + else if (mode == GFX_SETUP_DS_AA) + mode = GFX_SETUP_STANDARD_AA; } + + if (_actualGraphicsMode == mode) + return; + + printf("switchVideoMode %d\n", mode); + + gfx_video_setup_t setup = static_cast (mode); + gfx_video_deinit(); + gfx_video_init(GFX_MODE_AUTO, setup); + gfx_init(); + + _actualGraphicsMode = mode; + + gfx_coords(&_coordsOverlay, &_texOverlay, GFX_COORD_FULLSCREEN); + gfx_coords(&_coordsGame, &_texGame, GFX_COORD_FULLSCREEN); + updateScreenResolution(); } const OSystem::GraphicsMode* OSystem_Wii::getSupportedGraphicsModes() const { @@ -117,42 +146,26 @@ const OSystem::GraphicsMode* OSystem_Wii::getSupportedGraphicsModes() const { } int OSystem_Wii::getDefaultGraphicsMode() const { - return GM_DEFAULT; + return GFX_SETUP_STANDARD; } bool OSystem_Wii::setGraphicsMode(int mode) { - s16 xar, yar; - - printf("setGraphicsMode %d\n", mode); - - xar = vmode->viWidth / 2; - yar = vmode->xfbHeight / 2; - -#ifndef GAMECUBE - if (CONF_GetAspectRatio() && !_fullscreen) - xar = s16(float(xar) / 1.33f); -#endif - - GX_SetCamPosZ(400 - mode * 10); - GX_Start(640, 480, xar, yar); - - _activeGraphicsMode = mode; - + _configGraphicsMode = mode; return true; } int OSystem_Wii::getGraphicsMode() const { - return _activeGraphicsMode; + return _configGraphicsMode; } #ifdef USE_RGB_COLOR Graphics::PixelFormat OSystem_Wii::getScreenFormat() const { - return _screenPF; + return _pfGame; } Common::List OSystem_Wii::getSupportedFormats() { Common::List res; - res.push_back(_texturePF); + res.push_back(_pfRGB565); res.push_back(Graphics::PixelFormat::createFormatCLUT8()); return res; @@ -162,9 +175,11 @@ Common::List OSystem_Wii::getSupportedFormats() { void OSystem_Wii::initSize(uint width, uint height, const Graphics::PixelFormat *format) { bool update = false; + gfx_tex_format_t tex_format; #ifdef USE_RGB_COLOR Graphics::PixelFormat newFormat; + if (format) newFormat = *format; else @@ -173,8 +188,8 @@ void OSystem_Wii::initSize(uint width, uint height, if (newFormat.bytesPerPixel > 2) newFormat = Graphics::PixelFormat::createFormatCLUT8(); - if (_screenPF != newFormat) { - _screenPF = newFormat; + if (_pfGame != newFormat) { + _pfGame = newFormat; update = true; } #endif @@ -187,83 +202,147 @@ void OSystem_Wii::initSize(uint width, uint height, update = true; } - if (update) { -#ifdef USE_RGB_COLOR - printf("initSize %u*%u*%u (%u,%u,%u)\n", - _gameWidth, _gameHeight, - _screenPF.bytesPerPixel * 8, - _screenPF.rShift, _screenPF.gShift, _screenPF.bShift); -#else - printf("initSize %u*%u\n", _gameWidth, _gameHeight); -#endif + if (_gameRunning) { + switchVideoMode(_configGraphicsMode); + + if (_arCorrection && (_gameWidth == 320) && (_gameHeight == 200)) + gfx_set_ar(320.0 / 240.0); + else + gfx_set_ar(f32(_gameWidth) / f32(_gameHeight)); + } + if (update) { if(_gamePixels) free(_gamePixels); + tex_format = GFX_TF_PALETTE_RGB565; + #ifdef USE_RGB_COLOR + if (_pfGame.bytesPerPixel > 1) { + tex_format = GFX_TF_RGB565; + _pfGameTexture = _pfRGB565; + } + + printf("initSize %u*%u*%u (%u%u%u -> %u%u%u match: %d)\n", + _gameWidth, _gameHeight, _pfGame.bytesPerPixel * 8, + 8 - _pfGame.rLoss, 8 - _pfGame.gLoss, 8 - _pfGame.bLoss, + 8 - _pfGameTexture.rLoss, 8 - _pfGameTexture.gLoss, + 8 - _pfGameTexture.bLoss, _pfGame == _pfGameTexture); + _gamePixels = (u8 *) memalign(32, _gameWidth * _gameHeight * - _screenPF.bytesPerPixel); + _pfGame.bytesPerPixel); memset(_gamePixels, 0, _gameWidth * _gameHeight * - _screenPF.bytesPerPixel); + _pfGame.bytesPerPixel); #else + printf("initSize %u*%u\n", _gameWidth, _gameHeight); + _gamePixels = (u8 *) memalign(32, _gameWidth * _gameHeight); memset(_gamePixels, 0, _gameWidth * _gameHeight); #endif - if (!_overlayVisible) { - _currentWidth = _gameWidth; - _currentHeight = _gameHeight; - updateEventScreenResolution(); + + if (!gfx_tex_init(&_texGame, tex_format, TLUT_GAME, + _gameWidth, _gameHeight)) { + printf("could not init the game texture\n"); + ::abort(); } - setGraphicsMode(_activeGraphicsMode); + gfx_coords(&_coordsGame, &_texGame, GFX_COORD_FULLSCREEN); + + updateScreenResolution(); } } int16 OSystem_Wii::getWidth() { - return _gameWidth; + return _currentWidth; } int16 OSystem_Wii::getHeight() { - return _gameHeight; + return _currentHeight; } void OSystem_Wii::setPalette(const byte *colors, uint start, uint num) { #ifdef USE_RGB_COLOR - assert(_screenPF.bytesPerPixel == 1); + assert(_pfGame.bytesPerPixel == 1); #endif - const byte *p = colors; + const byte *s = colors; + u16 *d = _texGame.palette; + for (uint i = 0; i < num; ++i) { - _palette[start + i] = Graphics::RGBToColor >(p[0], p[1], p[2]); - p += 4; + d[start + i] = Graphics::RGBToColor >(s[0], s[1], s[2]); + s += 4; + } + + gfx_tex_flush_palette(&_texGame); + + if (_cursorPaletteDisabled) { + assert(_texMouse.palette); + + s = colors; + d = _texMouse.palette; + + for (uint i = 0; i < num; ++i) { + d[start + i] = Graphics::ARGBToColor >(0xff, s[0], s[1], s[2]); + s += 4; + } + + _cursorPaletteDirty = true; } } void OSystem_Wii::grabPalette(byte *colors, uint start, uint num) { - byte *p = colors; +#ifdef USE_RGB_COLOR + assert(_pfGame.bytesPerPixel == 1); +#endif + + u16 *s = _texGame.palette; + byte *d = colors; + u8 r, g, b; for (uint i = 0; i < num; ++i) { - Graphics::colorToRGB >(_palette[start + i], r, g, b); - p[0] = r; - p[1] = g; - p[2] = b; - p[3] = 0xff; - p += 4; + Graphics::colorToRGB >(s[start + i], r, g, b); + d[0] = r; + d[1] = g; + d[2] = b; + d[3] = 0xff; + d += 4; } } void OSystem_Wii::setCursorPalette(const byte *colors, uint start, uint num) { - const byte *p = colors; + if (!_texMouse.palette) { + printf("switching to palette based cursor\n"); + + if (!gfx_tex_init(&_texMouse, GFX_TF_PALETTE_RGB5A3, TLUT_MOUSE, + 16, 16)) { + printf("could not init the mouse texture\n"); + ::abort(); + } + } + + if (_cursorPaletteDisabled) { + memcpy(_cursorPalette, _texMouse.palette, 256 * 2); + _cursorPaletteDisabled = false; + } + + const byte *s = colors; + u16 *d = _texMouse.palette; + for (uint i = 0; i < num; ++i) { - _cursorPalette[start + i] = Graphics::RGBToColor >(p[0], p[1], p[2]); - p += 4; + d[start + i] = Graphics::ARGBToColor >(0xff, s[0], s[1], s[2]); + s += 4; } - _cursorPaletteDisabled = false; + _cursorPaletteDirty = true; } void OSystem_Wii::disableCursorPalette(bool disable) { _cursorPaletteDisabled = disable; + + if (_texMouse.palette && disable) { + memcpy(_texMouse.palette, _cursorPalette, 256 * 2); + _cursorPaletteDirty = true; + } } void OSystem_Wii::copyRectToScreen(const byte *buf, int pitch, int x, int y, @@ -274,12 +353,12 @@ void OSystem_Wii::copyRectToScreen(const byte *buf, int pitch, int x, int y, assert(h > 0 && y + h <= _gameHeight); #ifdef USE_RGB_COLOR - if (_screenPF.bytesPerPixel > 1) { + if (_pfGame.bytesPerPixel > 1) { if (!Graphics::crossBlit(_gamePixels + - y * _gameWidth * _screenPF.bytesPerPixel + - x * _screenPF.bytesPerPixel, - buf, _gameWidth * _screenPF.bytesPerPixel, - pitch, w, h, _texturePF, _screenPF)) { + y * _gameWidth * _pfGame.bytesPerPixel + + x * _pfGame.bytesPerPixel, + buf, _gameWidth * _pfGame.bytesPerPixel, + pitch, w, h, _pfGameTexture, _pfGame)) { printf("crossBlit failed\n"); ::abort(); } @@ -298,17 +377,13 @@ void OSystem_Wii::copyRectToScreen(const byte *buf, int pitch, int x, int y, #ifdef USE_RGB_COLOR } #endif + + _gameDirty = true; } void OSystem_Wii::updateScreen() { - static u32 x, y, h, skip; - static s16 msx, msy, mox, moy, mskip; - static u16 mpx, mpy; - static u8 *s; -#ifdef USE_RGB_COLOR - static u16 *s2; -#endif - static u16 *d, *p; + static gfx_coords_t cc; + static int cs; u32 now = getMillis(); if (now - _lastScreenUpdate < 1000 / MAX_FPS) @@ -318,111 +393,52 @@ void OSystem_Wii::updateScreen() { wii_memstats(); #endif + cs = _cursorScale; _lastScreenUpdate = now; - h = 0; - if (_overlayVisible) { - memcpy(_texture, _overlayPixels, _overlaySize); - } else { -#ifdef USE_RGB_COLOR - if (_screenPF.bytesPerPixel > 1) { - memcpy(_texture, _gamePixels, - _gameWidth * _gameHeight * _screenPF.bytesPerPixel); - } else { -#endif - for (y = 0; y < _gameHeight; ++y) { - for (x = 0; x < _gameWidth; ++x) - _texture[h + x] = _palette[_gamePixels[h + x]]; + gfx_frame_start(); - h += _gameWidth; - } -#ifdef USE_RGB_COLOR + + if (_gameRunning) { + if (_gameDirty) { + gfx_tex_convert(&_texGame, _gamePixels); + _gameDirty = false; } -#endif + + gfx_draw_tex(&_texGame, &_coordsGame); } - if (_mouseVisible) { - msx = _mouseX - _mouseHotspotX; - msy = _mouseY - _mouseHotspotY; - mox = 0; - moy = 0; - mpx = _mouseWidth; - mpy = _mouseHeight; - - if (msx < 0) { - mox = -msx; - mpx -= mox; - msx = 0; - } else - if (msx + mpx > _currentWidth - 1) - mpx = _currentWidth - msx - 1; - - if (msy < 0) { - moy = -msy; - mpy -= moy; - msy = 0; - } else - if (msy + mpy + 1 > _currentHeight - 1) - mpy = _currentHeight - msy - 1; - - - if (_cursorPaletteDisabled) - p = _palette; + if (_overlayVisible) { + // ugly, but the modern theme sets a factor of 3, only god knows why + if (cs > 2) + cs = 1; else - p = _cursorPalette; - - skip = _currentWidth - mpx; - mskip = _mouseWidth - mpx; - -#ifdef USE_RGB_COLOR - if (_cursorPF.bytesPerPixel > 1) { - s2 = (u16 *) _mouseCursor + moy * _mouseWidth + mox; - d = _texture + (msy * _currentWidth + msx); - - for (y = 0; y < mpy; ++y) { - for (x = 0; x < mpx; ++x) { - if (*s2 == _mouseKeyColor) { - s2++; - d++; - - continue; - } + cs *= 2; - *d++ = *s2; - s2++; - } - - d += skip; - s2 += mskip; - } - } else { -#endif - s = _mouseCursor + moy * _mouseWidth + mox; - d = _texture + (msy * _currentWidth + msx); - - for (y = 0; y < mpy; ++y) { - for (x = 0; x < mpx; ++x) { - if (*s == _mouseKeyColor) { - s++; - d++; - - continue; - } + if (_overlayDirty) { + gfx_tex_convert(&_texOverlay, _overlayPixels); + _overlayDirty = false; + } - *d++ = p[*s]; - s++; - } + gfx_draw_tex(&_texOverlay, &_coordsOverlay); + } - d += skip; - s += mskip; - } -#ifdef USE_RGB_COLOR + if (_mouseVisible) { + cc.x = f32(_mouseX - cs * _mouseHotspotX) * _currentXScale; + cc.y = f32(_mouseY - cs * _mouseHotspotY) * _currentYScale; + cc.w = f32(_texMouse.width) * _currentXScale * cs; + cc.h = f32(_texMouse.height) * _currentYScale * cs; + + if (_texMouse.palette && _cursorPaletteDirty) { + _texMouse.palette[_mouseKeyColor] = 0; + gfx_tex_flush_palette(&_texMouse); + _cursorPaletteDirty = false; } -#endif + + gfx_draw_tex(&_texMouse, &cc); } - GX_Render(_currentWidth, _currentHeight, (u8 *) _texture, - _currentWidth * 2); + gfx_frame_end(); } Graphics::Surface *OSystem_Wii::lockScreen() { @@ -431,7 +447,7 @@ Graphics::Surface *OSystem_Wii::lockScreen() { _surface.h = _gameHeight; _surface.pitch = _gameWidth; #ifdef USE_RGB_COLOR - _surface.bytesPerPixel = _screenPF.bytesPerPixel; + _surface.bytesPerPixel = _pfGame.bytesPerPixel; #else _surface.bytesPerPixel = 1; #endif @@ -440,35 +456,31 @@ Graphics::Surface *OSystem_Wii::lockScreen() { } void OSystem_Wii::unlockScreen() { + _gameDirty = true; } void OSystem_Wii::setShakePos(int shakeOffset) { - GX_SetTexTrans(0, (float) -shakeOffset * ((float) vmode->efbHeight / - (float) _currentHeight)); + gfx_coords(&_coordsGame, &_texGame, GFX_COORD_FULLSCREEN); + _coordsGame.y -= f32(shakeOffset) * _currentYScale; } void OSystem_Wii::showOverlay() { _mouseX = _overlayWidth / 2; _mouseY = _overlayHeight / 2; _overlayVisible = true; - _currentWidth = _overlayWidth; - _currentHeight = _overlayHeight; - - updateEventScreenResolution(); + updateScreenResolution(); } void OSystem_Wii::hideOverlay() { _mouseX = _gameWidth / 2; _mouseY = _gameHeight / 2; _overlayVisible = false; - _currentWidth = _gameWidth; - _currentHeight = _gameHeight; - - updateEventScreenResolution(); + updateScreenResolution(); } void OSystem_Wii::clearOverlay() { memset(_overlayPixels, 0, _overlaySize); + _overlayDirty = true; } void OSystem_Wii::grabOverlay(OverlayColor *buf, int pitch) { @@ -515,6 +527,8 @@ void OSystem_Wii::copyRectToOverlay(const OverlayColor *buf, int pitch, int x, dst += _overlayWidth; } while (--h); } + + _overlayDirty = true; } int16 OSystem_Wii::getOverlayWidth() { @@ -526,7 +540,7 @@ int16 OSystem_Wii::getOverlayHeight() { } Graphics::PixelFormat OSystem_Wii::getOverlayFormat() const { - return Graphics::createPixelFormat<565>(); + return Graphics::createPixelFormat<3444>(); } bool OSystem_Wii::showMouse(bool visible) { @@ -545,34 +559,103 @@ void OSystem_Wii::setMouseCursor(const byte *buf, uint w, uint h, int hotspotX, int hotspotY, uint32 keycolor, int cursorTargetScale, const Graphics::PixelFormat *format) { - (void) cursorTargetScale; // TODO + gfx_tex_format_t tex_format = GFX_TF_PALETTE_RGB5A3; + uint tw, th; + bool tmpBuf = false; + uint32 oldKeycolor = _mouseKeyColor; #ifdef USE_RGB_COLOR if (!format) - _cursorPF = Graphics::PixelFormat::createFormatCLUT8(); + _pfCursor = Graphics::PixelFormat::createFormatCLUT8(); else - _cursorPF = *format; + _pfCursor = *format; - if (_cursorPF.bytesPerPixel > 1) + if (_pfCursor.bytesPerPixel > 1) { + tex_format = GFX_TF_RGB5A3; _mouseKeyColor = keycolor & 0xffff; - else + tw = ROUNDUP(w, 4); + th = ROUNDUP(h, 4); + + if (_pfCursor != _pfRGB3444) + tmpBuf = true; + } else { #endif _mouseKeyColor = keycolor & 0xff; + tw = ROUNDUP(w, 8); + th = ROUNDUP(h, 4); +#ifdef USE_RGB_COLOR + } +#endif - _mouseWidth = w; - _mouseHeight = h; - _mouseHotspotX = hotspotX; - _mouseHotspotY = hotspotY; + if (!gfx_tex_init(&_texMouse, tex_format, TLUT_MOUSE, tw, th)) { + printf("could not init the mouse texture\n"); + ::abort(); + } + + if ((tw != w) || (th != h)) + tmpBuf = true; - if (_mouseCursor) - free(_mouseCursor); + if (!tmpBuf) { + gfx_tex_convert(&_texMouse, buf); + } else { + u8 bpp = _texMouse.bpp; + byte *tmp = (byte *) malloc(tw * th * bpp); + + if (!tmp) { + printf("could not alloc temp cursor buffer\n"); + ::abort(); + } + + if (bpp > 1) + memset(tmp, 0, tw * th * bpp); + else + memset(tmp, _mouseKeyColor, tw * th); #ifdef USE_RGB_COLOR - _mouseCursor = (u8 *) memalign(32, w * h * _cursorPF.bytesPerPixel); - memcpy(_mouseCursor, buf, w * h * _cursorPF.bytesPerPixel); -#else - _mouseCursor = (u8 *) memalign(32, w * h); - memcpy(_mouseCursor, buf, w * h); + if (bpp > 1) { + if (!Graphics::crossBlit(tmp, buf, + tw * _pfRGB3444.bytesPerPixel, + w * _pfCursor.bytesPerPixel, + tw, th, _pfRGB3444, _pfCursor)) { + printf("crossBlit failed\n"); + ::abort(); + } + + // nasty, shouldn't the frontend set the alpha channel? + u16 *s = (u16 *) buf; + u16 *d = (u16 *) tmp; + for (u16 y = 0; y < h; ++y) { + for (u16 x = 0; x < w; ++x) { + if (*s++ != _mouseKeyColor) + *d++ |= 7 << 12; + else + d++; + } + + d += tw - w; + } + } else { #endif + byte *dst = tmp; + + do { + memcpy(dst, buf, w * bpp); + buf += w * bpp; + dst += tw * bpp; + } while (--h); +#ifdef USE_RGB_COLOR + } +#endif + + gfx_tex_convert(&_texMouse, tmp); + free(tmp); + } + + _mouseHotspotX = hotspotX; + _mouseHotspotY = hotspotY; + _cursorScale = cursorTargetScale; + + if ((_texMouse.palette) && (oldKeycolor != _mouseKeyColor)) + _cursorPaletteDirty = true; } -- cgit v1.2.3