scummvm/backends/wince/screen.cpp

3168 lines
78 KiB
C++

/* ScummVM - Scumm Interpreter
* Copyright (C) 2001/2002 The ScummVM project
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* $Header$
*
*/
#ifdef _WIN32_WCE
/* Original GFX code by Vasyl Tsvirkunov */
#include "wince.h"
//#include <windows.h>
//#include <Aygshell.h>
//#include "gx.h"
//#include "screen.h"
//#include "resource.h"
//#include "dynamic_imports.h"
#include <tlhelp32.h>
#define COLORCONV565(r,g,b) \
(((r&0xf8)<<(11-3))|((g&0xfc)<<(5-2))|((b&0xf8)>>3))
#define COLORCONV555(r,g,b) \
(((r&0xf8)<<(10-3))|((g&0xf8)<<(5-2))|((b&0xf8)>>3))
#define COLORCONVMONO(r,g,b) ((((3*r>>3)+(g>>1)+(b>>3))>>colorscale)^invert)
#define RED_FROM_565(x) ((((x)>>11)&0x1F) << 3)
#define GREEN_FROM_565(x) ((((x)>>5)&0x3F) << 2)
#define BLUE_FROM_565(x) (((x)&0x1F) << 3)
#define MAX_CLR 0x100
static UBYTE palRed[MAX_CLR];
static UBYTE palGreen[MAX_CLR];
static UBYTE palBlue[MAX_CLR];
static unsigned short pal[MAX_CLR];
/* First 10 and last 10 colors on palettized devices require special treatment */
static UBYTE staticTranslate[20];
static UBYTE invert = 0;
static int colorscale = 0;
unsigned char color_match[500]; // used for paletted issues
extern const char *getBuildDate();
extern UBYTE item_toolbar[];
extern UBYTE item_toolbar_colors[];
extern UBYTE item_toolbarPortrait[];
extern UBYTE item_toolbarPortrait_colors[];
extern UBYTE item_disk[];
extern UBYTE item_disk_colors[];
extern UBYTE item_skip[];
extern UBYTE item_skip_colors[];
extern UBYTE item_soundOff[];
extern UBYTE item_soundOff_colors[];
extern UBYTE item_soundOn[];
extern UBYTE item_soundOn_colors[];
extern UBYTE item_monkeyPortrait[];
extern UBYTE item_monkeyPortrait_colors[];
extern UBYTE item_monkeyLandscape[];
extern UBYTE item_monkeyLandscape_colors[];
extern UBYTE item_keyboard[];
extern UBYTE item_keyboard_colors[];
extern UBYTE item_keyboardPortrait[];
extern UBYTE item_keyboardPortrait_colors[];
extern UBYTE item_loading[];
extern UBYTE item_loading_colors[];
extern UBYTE item_startup[];
extern UBYTE item_startup_colors[];
extern int item_startup_colors_size;
extern UBYTE item_bomb[];
extern UBYTE item_bomb_colors[];
extern bool sound_activated;
extern bool hide_toolbar;
extern bool is_simon;
extern bool smartphone;
extern bool high_res;
extern NewGui *g_gui;
bool toolbar_drawn;
bool draw_keyboard;
bool wide_screen;
bool extra_wide_screen;
GXDisplayProperties gxdp;
int active;
UBYTE decomp[320 * 240];
UBYTE comment_zone[8 * 220];
UBYTE highlighted_zone[8 * 220];
int _highlighted_index = -1;
bool _gfx_mode_switch;
int _game_selection_X_offset;
int _game_selection_Y_offset;
float _screen_factor;
struct tScreenGeometry
{
long width;
long height;
long startoffset;
long sourceoffset;
long linestep;
long pixelstep;
long xSkipMask;
long xLimit;
long lineLimit;
};
tScreenGeometry geom[3];
tScreenGeometry portrait_geometry;
int currentScreenMode = 0;
int useMode = 0;
int maxMode = 2;
int filter_available;
int smooth_filter;
int toolbar_available;
UBYTE *toolbar = NULL;
UBYTE *displayCache;
#ifndef NEW_GAPI_CODE
UBYTE *noGAPI_video_buffer = NULL;
HDC noGAPI_compat;
#else
UBYTE *noGAPI_buffer;
HBITMAP noGAPI_bitmap;
BITMAPINFOHEADER noGAPI_bitmap_header;
HDC noGAPI_compat;
#endif
char noGAPI = 0;
/* Using vectorized function to save on branches */
typedef void (*tScreenOp)();
typedef void (*tCls)();
typedef void (*tBlt)(UBYTE*);
typedef void (*tBlt_part)(UBYTE*,int, int, int, int, UBYTE*, int, BOOL = FALSE);
typedef void (*tSet_565)(INT16 *buffer, int pitch, int x, int y, int width, int height);
void mono_Cls();
void mono_Blt(UBYTE*);
void mono_Blt_part(UBYTE*, int, int, int, int, UBYTE*, int, BOOL = FALSE);
void mono_Set_565(INT16*, int, int, int, int, int);
void palette_Cls();
void palette_Blt(UBYTE*);
void palette_Blt_part(UBYTE*, int, int, int, int, UBYTE*, int, BOOL = FALSE);
void palette_Set_565(INT16*, int, int, int, int, int);
void hicolor_Cls();
void hicolor555_Blt(UBYTE*);
void hicolor555_Blt_part(UBYTE*, int, int, int, int, UBYTE*, int, BOOL = FALSE);
void hicolor555_Set_565(INT16*, int, int, int, int, int);
void hicolor565_Blt(UBYTE*);
void hicolor565_Blt_part(UBYTE*, int, int, int, int, UBYTE*, int, BOOL = FALSE);
//void hicolor565_Get_565(INT16*, int, int, int, int, int);
void hicolor565_Set_565(INT16*, int, int, int, int, int);
void noGAPI_Cls();
void noGAPI_Blt(UBYTE*);
void noGAPI_Blt_part(UBYTE*, int, int, int, int, UBYTE*, int, BOOL = FALSE);
void noGAPI_Set_565(INT16*, int, int, int, int, int);
//void NULL_Get_565(INT16*, int, int, int, int, int);
void NULL_Set_565(INT16*, int, int, int, int, int);
void palette_update();
void printString(const char *, int, int, int, int = -1, int = 220);
int drawString(const char *, int, int, int, int = -1);
static byte textfont[] = {0,0,99,1,226,8,4,8,6,8,6,0,0,0,0,0,0,0,0,0,0,0,8,2,1,8,0,0,0,0,0,0,0,0,0,0,0,0,4,3,7,8,7,7,8,4,5,5,8,7,4,7,3,8,7,7,7,7,8,7,7,7,7,7,3,4,7,5,7,7,8,7,7,7,7,7,7,7,7,5,7,7,
7,8,7,7,7,7,7,7,7,7,7,8,7,7,7,5,8,5,8,8,7,7,7,6,7,7,7,7,7,5,6,7,5,8,7,7,7,7,7,7,7,7,7,8,7,7,7,5,3,5,0,8,7,7,7,7,7,7,0,6,7,7,7,5,5,5,7,0,6,8,8,7,7,7,7,7,0,7,7,0,0,
0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,0,0,0,0,0,0,0,0,1,3,6,12,
24,62,3,0,128,192,96,48,24,124,192,0,0,3,62,24,12,6,3,1,0,192,124,24,48,96,192,128,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,237,74,72,0,0,0,0,0,128,128,128,0,0,0,0,0,0,0,0,0,0,0,0,0,60,66,153,161,161,153,66,60,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,96,96,96,96,0,0,96,0,102,102,102,0,0,0,0,0,102,102,255,102,255,102,102,0,24,62,96,60,6,124,24,0,98,102,12,24,48,102,70,0,60,102,60,56,103,102,63,0,96,48,16,0,0,0,0,0,24,48,96,96,96,48,24,0,96,48,24,24,24,48,96,0,
0,102,60,255,60,102,0,0,0,24,24,126,24,24,0,0,0,0,0,0,0,48,48,96,0,0,0,126,0,0,0,0,0,0,0,0,0,96,96,0,0,3,6,12,24,48,96,0,60,102,102,102,102,102,60,0,24,24,56,24,24,24,126,0,60,102,6,12,48,96,126,0,60,102,6,28,6,102,60,0,6,
14,30,102,127,6,6,0,126,96,124,6,6,102,60,0,60,102,96,124,102,102,60,0,126,102,12,24,24,24,24,0,60,102,102,60,102,102,60,0,60,102,102,62,6,102,60,0,0,0,96,0,0,96,0,0,0,0,48,0,0,48,48,96,14,24,48,96,48,24,14,0,0,0,120,0,120,0,0,0,112,24,
12,6,12,24,112,0,60,102,6,12,24,0,24,0,0,0,0,255,255,0,0,0,24,60,102,126,102,102,102,0,124,102,102,124,102,102,124,0,60,102,96,96,96,102,60,0,120,108,102,102,102,108,120,0,126,96,96,120,96,96,126,0,126,96,96,120,96,96,96,0,60,102,96,110,102,102,60,0,102,102,102,
126,102,102,102,0,120,48,48,48,48,48,120,0,30,12,12,12,12,108,56,0,102,108,120,112,120,108,102,0,96,96,96,96,96,96,126,0,99,119,127,107,99,99,99,0,102,118,126,126,110,102,102,0,60,102,102,102,102,102,60,0,124,102,102,124,96,96,96,0,60,102,102,102,102,60,14,0,124,102,102,124,
120,108,102,0,60,102,96,60,6,102,60,0,126,24,24,24,24,24,24,0,102,102,102,102,102,102,60,0,102,102,102,102,102,60,24,0,99,99,99,107,127,119,99,0,102,102,60,24,60,102,102,0,102,102,102,60,24,24,24,0,126,6,12,24,48,96,126,0,120,96,96,96,96,96,120,0,3,6,12,24,48,
96,192,0,120,24,24,24,24,24,120,0,0,0,0,0,0,219,219,0,0,0,0,0,0,0,0,255,102,102,102,0,0,0,0,0,0,0,60,6,62,102,62,0,0,96,96,124,102,102,124,0,0,0,60,96,96,96,60,0,0,6,6,62,102,102,62,0,0,0,60,102,126,96,60,0,0,14,24,62,24,24,
24,0,0,0,62,102,102,62,6,124,0,96,96,124,102,102,102,0,0,48,0,112,48,48,120,0,0,12,0,12,12,12,12,120,0,96,96,108,120,108,102,0,0,112,48,48,48,48,120,0,0,0,102,127,127,107,99,0,0,0,124,102,102,102,102,0,0,0,60,102,102,102,60,0,0,0,124,102,102,124,96,
96,0,0,62,102,102,62,6,6,0,0,124,102,96,96,96,0,0,0,62,96,60,6,124,0,0,24,126,24,24,24,14,0,0,0,102,102,102,102,62,0,0,0,102,102,102,60,24,0,0,0,99,107,127,62,54,0,0,0,102,60,24,60,102,0,0,0,102,102,102,62,12,120,0,0,126,12,24,48,126,0,
24,48,48,96,48,48,24,0,96,96,96,0,96,96,96,0,96,48,48,24,48,48,96,0,0,0,0,0,0,0,0,0,8,12,14,255,255,14,12,8,60,102,96,96,102,60,24,56,102,0,102,102,102,102,62,0,12,24,60,102,126,96,60,0,24,36,60,6,62,102,62,0,102,0,60,6,62,102,62,0,48,
24,60,6,62,102,62,0,0,0,0,0,0,0,0,0,0,60,96,96,96,60,24,56,24,36,60,102,126,96,60,0,102,0,60,102,126,96,60,0,48,24,60,102,126,96,60,0,0,216,0,112,48,48,120,0,48,72,0,112,48,48,120,0,96,48,0,112,48,48,120,0,102,24,60,102,126,102,102,0,0,0,
0,0,0,0,0,0,24,48,124,96,120,96,124,0,0,0,108,26,126,216,110,0,30,40,40,126,72,136,142,0,24,36,60,102,102,102,60,0,102,0,60,102,102,102,60,0,48,24,60,102,102,102,60,0,24,36,0,102,102,102,62,0,48,24,102,102,102,102,62,0,0,0,0,0,0,0,0,0,102,60,102,
102,102,102,60,0,102,0,102,102,102,102,60,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,12,24,60,6,62,102,62,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,28,54,54,124,102,102,124,64,0,0,0};
static tCls pCls = NULL;
static tBlt pBlt = NULL;
static tBlt_part pBlt_part = NULL;
static tSet_565 pSet_565 = NULL;
static tScreenOp pBeginDraw = NULL;
static tScreenOp pEndDraw = NULL;
static int _geometry_w;
static int _geometry_h;
static int _saved_geometry_h;
HWND hWndMain;
typedef enum {
DEVICE_HPC = 0,
DEVICE_PPC,
DEVICE_SMARTPHONE
} pdaDevice;
typedef enum {
DEVICE_GAPI = 0,
DEVICE_VIDEO,
DEVICE_GDI
} gfxDevice;
typedef enum {
VIDEO_565 = 0,
VIDEO_555,
VIDEO_PALETTED,
VIDEO_MONO,
VIDEO_DONT_CARE
} gfxOption;
unsigned char* pda_device_name[] = {
(unsigned char*)"HPC",
(unsigned char*)"PPC",
(unsigned char*)"Smartphone"
};
unsigned char* gfx_device_name[] = {
(unsigned char*)"GAPI",
(unsigned char*)"Direct Video",
(unsigned char*)"GDI"
};
unsigned char* gfx_device_options_name[] = {
(unsigned char*)"565",
(unsigned char*)"555",
(unsigned char*)"paletted",
(unsigned char*)"mono",
(unsigned char*)"",
};
pdaDevice _pda_device;
gfxDevice _gfx_device;
gfxOption _gfx_option;
unsigned char *image_expand(unsigned char *src) {
int i = 0;
int j;
int expanded = 0;
for (;;) {
if (!src[i]) {
if (!src[i + 1])
break;
for (j=0; j<src[i + 1]; j++)
decomp[expanded++] = src[i+2];
i += 3;
}
else
decomp[expanded++] = src[i++];
}
return decomp;
}
void SetScreenMode(int mode)
{
currentScreenMode = mode;
if(currentScreenMode > maxMode)
currentScreenMode = 0;
}
int GetScreenMode()
{
return currentScreenMode;
}
void GraphicsSuspend()
{
if(active)
{
active = 0;
dynamicGXSuspend();
}
}
void GraphicsResume()
{
if(!active)
{
active = 1;
dynamicGXResume();
}
palette_update();
}
void GraphicsOff(void)
{
dynamicGXCloseDisplay();
active = 0;
}
void GAPIBeginDraw() {
displayCache = (UBYTE*)dynamicGXBeginDraw();
}
void GAPIEndDraw() {
dynamicGXEndDraw();
}
void SetScreenGeometry(int w, int h) {
// Complain (loudly) if w > 320 and h > 240 ...
/*
if (w != 320 || h > 240) {
char tempo[100];
sprintf(tempo, "Unsupported screen geometry %dx%d", w, h);
drawError(tempo);
exit(1);
}
*/
_geometry_w = w;
_geometry_h = h;
_saved_geometry_h = h;
RestoreScreenGeometry();
}
void LimitScreenGeometry() {
int limit;
if (high_res) {
if (wide_screen)
limit = 440;
else
limit = 400;
}
else
limit = 200;
if (_geometry_h > limit) {
geom[0].lineLimit = _geometry_w*limit;
geom[1].lineLimit = _geometry_w*limit;
geom[2].lineLimit = _geometry_w*limit;
_geometry_h = limit;
}
}
void RestoreScreenGeometry() {
_geometry_h = _saved_geometry_h;
geom[0].lineLimit = _geometry_w * _geometry_h;
geom[1].lineLimit = _geometry_w * _geometry_h;
geom[2].lineLimit = _geometry_w * _geometry_h;
}
int GraphicsOn(HWND hWndMain_param, bool gfx_mode_switch)
{
hWndMain = hWndMain_param;
_gfx_device = DEVICE_GAPI;
if (!noGAPI && dynamicGXOpenDisplay(hWndMain, GX_FULLSCREEN) == GAPI_SIMU)
_gfx_device = DEVICE_VIDEO;
_gfx_mode_switch = gfx_mode_switch;
if (_gfx_mode_switch) {
_game_selection_X_offset = GAME_SELECTION_X_OFFSET;
_game_selection_Y_offset = GAME_SELECTION_Y_OFFSET;
}
else {
_game_selection_X_offset = 0;
_game_selection_Y_offset = 0;
}
memset(&gxdp, 0, sizeof(gxdp));
if (!noGAPI)
gxdp = dynamicGXGetDisplayProperties();
else {
gxdp.cxWidth = GetSystemMetrics(SM_CXSCREEN);
gxdp.cyHeight = GetSystemMetrics(SM_CYSCREEN);
gxdp.ffFormat = 0xA8;
}
// Possible Aero problem
if (gxdp.cbxPitch == 61440 &&
gxdp.cbyPitch == -2 &&
gxdp.ffFormat == 0x18
) {
gxdp.cbxPitch = 640;
gxdp.cbyPitch = -2;
gxdp.ffFormat = kfDirect | kfDirect565;
}
if(noGAPI)
{
HDC hdc;
int width = (!high_res ? 320 : 640);
int height = (!high_res ? 240 : 480);
pCls = noGAPI_Cls;
pBlt = noGAPI_Blt;
pBlt_part = noGAPI_Blt_part;
pSet_565 = noGAPI_Set_565;
toolbar_available = 1;
hdc = GetDC(hWndMain);
noGAPI_compat = CreateCompatibleDC(hdc);
ReleaseDC(hWndMain, hdc);
#ifndef NEW_GAPI_CODE
// Init GDI
noGAPI_video_buffer = (UBYTE*)malloc(320 * 240 * 2);
#else
memset(&noGAPI_bitmap_header, 0, sizeof(BITMAPINFOHEADER));
noGAPI_bitmap_header.biSize = sizeof(BITMAPINFOHEADER);
noGAPI_bitmap_header.biWidth = GetSystemMetrics(SM_CXSCREEN);
noGAPI_bitmap_header.biHeight = -GetSystemMetrics(SM_CYSCREEN); /* origin = top */
noGAPI_bitmap_header.biPlanes = 1;
noGAPI_bitmap_header.biBitCount = 24;
noGAPI_bitmap_header.biCompression = BI_RGB; /* paletted fixme Jornada 820 ? */
noGAPI_bitmap = CreateDIBSection(noGAPI_compat, (BITMAPINFO*)&noGAPI_bitmap_header, DIB_RGB_COLORS, (void**)&noGAPI_buffer, NULL, 0);
if (!noGAPI_bitmap)
exit(1);
SelectObject(noGAPI_compat, noGAPI_bitmap);
#endif
_gfx_device = DEVICE_GDI;
_gfx_option = VIDEO_DONT_CARE;
}
else if(gxdp.ffFormat & kfDirect565)
{
pCls = hicolor_Cls;
pBlt = hicolor565_Blt;
pBlt_part = hicolor565_Blt_part;
pSet_565 = hicolor565_Set_565;
pBeginDraw = GAPIBeginDraw;
pEndDraw = GAPIEndDraw;
filter_available = 1;
smooth_filter = 1;
toolbar_available = 1;
_gfx_option = VIDEO_565;
}
else if(gxdp.ffFormat & kfDirect555)
{
pCls = hicolor_Cls;
pBlt = hicolor555_Blt;
pBlt_part = hicolor555_Blt_part;
pSet_565 = hicolor555_Set_565;
pBeginDraw = GAPIBeginDraw;
pEndDraw = GAPIEndDraw;
filter_available = 1;
smooth_filter = 1;
toolbar_available = 1;
_gfx_option = VIDEO_555;
}
else if((gxdp.ffFormat & kfDirect) && (gxdp.cBPP <= 8))
{
pCls = mono_Cls;
pBlt = mono_Blt;
pBlt_part = mono_Blt_part;
pSet_565 = mono_Set_565;
pBeginDraw = GAPIBeginDraw;
pEndDraw = GAPIEndDraw;
if(gxdp.ffFormat & kfDirectInverted)
invert = (1<<gxdp.cBPP)-1;
colorscale = gxdp.cBPP < 8 ? 8-gxdp.cBPP : 0;
if(gxdp.cBPP >= 4)
filter_available = 1;
toolbar_available = 1;
_gfx_option = VIDEO_MONO;
}
else if(gxdp.ffFormat & kfPalette)
{
pCls = palette_Cls;
pBlt = palette_Blt;
pBlt_part = palette_Blt_part;
pSet_565 = palette_Set_565;
pBeginDraw = GAPIBeginDraw;
pEndDraw = GAPIEndDraw;
toolbar_available = 1;
_gfx_option = VIDEO_PALETTED;
}
if(!pCls || !pBlt || (!smartphone && (gxdp.cxWidth < 240 || gxdp.cyHeight < 240))
)
{
// I don't believe there are devices that end up here
GraphicsOff();
return 1;
}
if (smartphone)
toolbar_available = 0;
// compute geometries
// portrait
portrait_geometry.width = gxdp.cxWidth; // 240
portrait_geometry.height = gxdp.cyHeight; // 320
portrait_geometry.startoffset = 0;
portrait_geometry.sourceoffset = 0;
portrait_geometry.linestep = gxdp.cbyPitch;
portrait_geometry.pixelstep = gxdp.cbxPitch;
portrait_geometry.xSkipMask = gxdp.cxWidth < 320 ? 0x00000003 : 0xffffffff;
portrait_geometry.xLimit = 320; // skip 1/4
portrait_geometry.lineLimit = 320*200;
geom[0].width = gxdp.cxWidth;
geom[0].height = gxdp.cyHeight;
geom[0].startoffset = 0;
geom[0].sourceoffset = 0;
geom[0].linestep = gxdp.cbyPitch;
geom[0].pixelstep = gxdp.cbxPitch;
geom[0].xSkipMask = 0xffffffff;
geom[0].xLimit = 240;
geom[0].lineLimit = 320*240;
_screen_factor = 1/2;
// This will be overridden for the Smartphone implementation
// left handed landscape
geom[1].width = gxdp.cyHeight; // 320
geom[1].height = gxdp.cxWidth; // 240
geom[1].startoffset = gxdp.cbyPitch*(gxdp.cyHeight-1);
geom[1].sourceoffset = 0;
geom[1].linestep = gxdp.cbxPitch;
geom[1].pixelstep = -gxdp.cbyPitch;
geom[1].xSkipMask = 0xffffffff;
geom[1].xLimit = 320; // no skip
geom[1].lineLimit = 320*200;
// right handed landscape
geom[2].width = gxdp.cyHeight; // 320
geom[2].height = gxdp.cxWidth; // 240
geom[2].startoffset = gxdp.cbxPitch*(gxdp.cxWidth-1);
geom[2].sourceoffset = 0;
geom[2].linestep = -gxdp.cbxPitch;
geom[2].pixelstep = gxdp.cbyPitch;
geom[2].xSkipMask = 0xffffffff;
geom[2].xLimit = 320; // no skip
geom[2].lineLimit = 320*200;
if(gxdp.cyHeight < 320 && !smartphone)
maxMode = 0; // portrait only!
active = 1;
wide_screen = GetSystemMetrics(SM_CXSCREEN) >= 320;
extra_wide_screen = GetSystemMetrics(SM_CYSCREEN) >= 480;
if (wide_screen)
_pda_device = DEVICE_HPC;
else {
if (smartphone)
_pda_device = DEVICE_SMARTPHONE;
else
_pda_device = DEVICE_PPC;
}
return 0;
}
/* Find the best color match in the palette (limited to 'limit' entries) */
UBYTE best_match(UBYTE r, UBYTE g, UBYTE b, int limit)
{
UBYTE best = 0;
int distance = 768;
int i, d;
for(i=0; i<limit; i++)
{
/* Manhattan distance for now. Not the best but rather fast */
d = abs(r-palRed[i])+abs(g-palGreen[i])+abs(b-palBlue[i]);
if(d < distance)
{
distance = d;
best = i;
}
}
return (UBYTE)best;
}
void palette_update()
{
if(gxdp.ffFormat & kfPalette)
{
LOGPALETTE* ple =
(LOGPALETTE*)malloc(sizeof(LOGPALETTE)+sizeof(PALETTEENTRY)*255);
ple->palVersion = 0x300;
ple->palNumEntries = 256;
for(int i=0; i<236; i++) // first 10 and last ten belong to the system!
{
ple->palPalEntry[i+10].peBlue = palBlue[i];
ple->palPalEntry[i+10].peGreen = palGreen[i];
ple->palPalEntry[i+10].peRed = palRed[i];
ple->palPalEntry[i+10].peFlags = PC_RESERVED;
}
HDC hDC = GetDC(hWndMain);
GetSystemPaletteEntries(hDC, 0, 10, &(ple->palPalEntry[0]));
GetSystemPaletteEntries(hDC, 246, 10, &(ple->palPalEntry[246]));
HPALETTE hpal = CreatePalette(ple);
SelectPalette(hDC, hpal, FALSE);
RealizePalette(hDC);
DeleteObject((HGDIOBJ)hpal);
ReleaseDC(hWndMain, hDC);
free((void*)ple);
for(i=0; i<20; i++)
staticTranslate[i] = best_match(palRed[i+236], palGreen[i+236], palBlue[i+236], 236)+10;
memset(color_match, 255, sizeof(color_match));
}
}
void SetPalEntry(int ent, UBYTE r, UBYTE g, UBYTE b)
{
int i;
if (ent >= MAX_CLR)
return;
palRed[ent] = r;
palGreen[ent] = g;
palBlue[ent] = b;
if(gxdp.ffFormat & kfDirect565)
pal[ent] = COLORCONV565(r,g,b);
else if(gxdp.ffFormat & kfDirect555)
pal[ent] = COLORCONV555(r,g,b);
else if(gxdp.ffFormat & kfDirect)
pal[ent] = COLORCONVMONO(r,g,b);
}
/* *************** CLS IMPLEMENTATIONS ****************** */
void mono_Cls()
{
int x, y;
UBYTE* dst;
UBYTE *scraddr;
int linestep, pixelstep;
UBYTE fillcolor;
fillcolor = (gxdp.ffFormat & kfDirectInverted) ? 0xff : 0x00;
pixelstep = geom[0].pixelstep;
if(pixelstep == 0)
return;
linestep = (pixelstep > 0) ? -1 : 1;
scraddr = (UBYTE*)dynamicGXBeginDraw();
if(scraddr)
{
for(y=0; y<geom[0].height*gxdp.cBPP/8; y++)
{
dst = scraddr+geom[0].startoffset;
for(x=0; x<geom[0].width; x++)
{
*dst = fillcolor;
dst += pixelstep;
}
scraddr += linestep;
}
dynamicGXEndDraw();
}
}
void palette_Cls()
{
int x, y;
UBYTE* dst;
UBYTE *scraddr;
scraddr = (UBYTE*)dynamicGXBeginDraw();
if(scraddr)
{
for(y=0; y<geom[useMode].height; y++)
{
dst = scraddr+geom[useMode].startoffset;
for(x=0; x<geom[useMode].width; x++)
{
*dst = 0;
dst += geom[useMode].pixelstep;
}
scraddr += geom[useMode].linestep;
}
dynamicGXEndDraw();
}
}
void hicolor_Cls()
{
int x, y;
UBYTE* dst;
UBYTE *scraddr;
scraddr = (UBYTE*)dynamicGXBeginDraw();
if(scraddr)
{
for(y=0; y<geom[useMode].height; y++)
{
dst = scraddr+geom[useMode].startoffset;
for(x=0; x<geom[useMode].width; x++)
{
*(unsigned short*)dst = 0;
dst += geom[useMode].pixelstep;
}
scraddr += geom[useMode].linestep;
}
dynamicGXEndDraw();
}
}
void Cls()
{
pCls();
}
int counter = 0;
void drawSoundItem(int x, int y) {
if (!sound_activated)
pBlt_part(image_expand(item_soundOn), x, y, 32, 32, item_soundOn_colors, 0);
else
pBlt_part(image_expand(item_soundOff), x, y, 32, 32, item_soundOff_colors, 0);
}
void drawError(char *error) {
FILE *file_error;
file_error=fopen("scummvm_error.txt", "w");
if (file_error) {
fprintf(file_error, "%s\n", error);
fclose(file_error);
}
int current_y = 80;
Cls();
pBlt_part(image_expand(item_toolbar), 0, 0, 320, 40, item_toolbar_colors, 0);
pBlt_part(image_expand(item_bomb), 0, 0, 64, 67, item_bomb_colors, 0);
memset(decomp, 0, sizeof(decomp));
current_y = drawString("SCUMMVM ERROR !", 10, current_y, 2, 1);
current_y += 10;
current_y = drawString(error, 10, current_y, 8, 1);
current_y += 10;
current_y = drawString("Exiting in 10 seconds", 10, current_y, 8, 1);
Sleep(10 * 1000);
}
void drawWait() {
pBlt_part(image_expand(item_toolbar), 0, 0, 320, 40, item_toolbar_colors, 0);
pBlt_part(image_expand(item_loading), 28, 10, 100, 25, item_loading_colors, 0);
}
void drawWaitSelectKey() {
drawWait();
drawString("Press key for RIGHT CLICK", 10, 100, 2, 1);
}
void setGameSelectionPalette() {
int i;
if (_gfx_option != VIDEO_PALETTED)
return;
for (i=0; i<item_startup_colors_size; i++)
SetPalEntry(i, item_startup_colors[3 * i], item_startup_colors[(3 * i) + 1],
item_startup_colors[(3 * i) + 2]);
palette_update();
}
void drawBlankGameSelection() {
//int i;
image_expand(item_startup);
/* Store empty comment */
memcpy(comment_zone, decomp + (206 * 220), 8 * 220);
pBlt_part(decomp, _game_selection_X_offset, _game_selection_Y_offset, 220, 250, item_startup_colors, 0);
}
void drawVideoDevice() {
char info[100];
sprintf(info, "Video device : %s %s - CVS %s PPC %s", gfx_device_name[_gfx_device], gfx_device_options_name[_gfx_option], gScummVMVersion, getBuildDate());
drawString(info, 10, 0, 2, 1);
/*
printString(video_device, 10, 270, 2, 0);
pBlt_part(decomp + (270 * 220), 0, 5, 220, 8, item_startup_colors, 1);
*/
}
void drawCommentString(char *comment) {
/* Erase old comment */
memcpy(decomp + (206 * 220), comment_zone, 8 * 220);
/* Draw new comment */
printString(comment, 24, 206, 2);
pBlt_part(decomp + (206 * 220), _game_selection_X_offset, _game_selection_Y_offset + 206, 220, 8, item_startup_colors, 0);
}
void drawStandardString(char *game, int index) {
printString(game, 24, 70 + (15 * index), 2);
//pBlt_part(decomp, GAME_SELECTION_X_OFFSET + 24, GAME_SELECTION_Y_OFFSET + 70 + (12 * index), 220, 8, item_startup_colors);
pBlt_part(decomp + ((70 + (15 * index)) * 220), _game_selection_X_offset, _game_selection_Y_offset + 70 + (15 * index), 220, 8, item_startup_colors, 0);
}
void drawHighlightedString(char *game, int index) {
/* Replace former highlighted string */
if (_highlighted_index != -1) {
memcpy(decomp + ((70 + (15 * _highlighted_index)) * 220), highlighted_zone, 8 * 220);
pBlt_part(decomp + ((70 + (15 * _highlighted_index)) * 220), _game_selection_X_offset, _game_selection_Y_offset + 70 + (15 * _highlighted_index), 220, 8, item_startup_colors, 0);
}
/* Save non highlighted string */
_highlighted_index = index;
memcpy(highlighted_zone, decomp + ((70 + (15 * index)) * 220), 8 * 220);
/* Draw new highlighted string */
printString(game, 24, 70 + (15 * index), 2, 3);
pBlt_part(decomp + ((70 + (15 * index)) * 220), _game_selection_X_offset, _game_selection_Y_offset + 70 + (15 * index), 220, 8, item_startup_colors, 0);
}
void resetLastHighlighted() {
_highlighted_index = -1;
}
void reducePortraitGeometry() {
if (_gfx_mode_switch)
memcpy(&geom[0], &portrait_geometry, sizeof(tScreenGeometry));
}
void drawAllToolbar() {
int x,y;
int start_offset;
if (high_res && wide_screen)
start_offset = 440;
else
start_offset = 200;
if (currentScreenMode || wide_screen) {
if (draw_keyboard) {
pBlt_part(image_expand(item_keyboard), 0, start_offset, 320, 40, item_keyboard_colors, 0);
}
else {
pBlt_part(image_expand(item_toolbar), 0, start_offset, 320, 40, item_toolbar_colors, 0);
x = 10;
y = start_offset + 4;
if (!is_simon)
pBlt_part(image_expand(item_disk), x, y, 32, 32, item_disk_colors, 0);
x += 40;
pBlt_part(image_expand(item_skip), x, y, 32, 32, item_skip_colors, 0);
x += 40;
drawSoundItem(x, y);
if (_gfx_mode_switch && !high_res) {
x += 40;
pBlt_part(image_expand(item_monkeyPortrait), x, y, 32, 32,
item_monkeyPortrait_colors, 0);
}
}
}
else {
if (draw_keyboard) {
pBlt_part(image_expand(item_keyboardPortrait), 0, 240, 320, 80,
item_keyboardPortrait_colors, 0);
}
else {
pBlt_part(image_expand(item_toolbarPortrait), 0, 240, 320, 80,
item_toolbarPortrait_colors, 0);
/*drawToolbarItem(item_toolbarPortrait_colors, item_toolbarPortrait,
0, 240, 240, 80);*/
x = 10;
y = 240;
pBlt_part(image_expand(item_disk), x, y, 32, 32, item_disk_colors, 0);
x += 40;
pBlt_part(image_expand(item_skip), x, y, 32, 32, item_skip_colors, 0);
x += 40;
drawSoundItem(x, y);
if (_gfx_mode_switch && !high_res) {
x += 40;
pBlt_part(image_expand(item_monkeyLandscape), x, y, 32, 32,
item_monkeyLandscape_colors, 0);
}
}
}
toolbar_drawn = true;
}
void redrawSoundItem() {
drawSoundItem(10 + 40 + 40, (currentScreenMode || wide_screen ? 204 : 240));
}
bool isInBox(int x, int y, int x1, int y1, int x2, int y2) {
return ((x >= x1 && y >= y1) && (x <= x2 && y <= y2));
}
ToolbarSelected getToolbarSelection (int x, int y) {
int test_x, test_y;
int offset = 1;
/*
if (!currentScreenMode)
return ToolbarNone;
*/
if (!high_res && !(x >= 10 && y >= 204))
return ToolbarNone;
if (high_res && !(x >= 10 && y >= 444))
return ToolbarNone;
if (!high_res)
test_y = (currentScreenMode || wide_screen ? 204 : 240);
else
test_y = 444;
if (high_res && !wide_screen)
offset = 2;
test_x = (10 * offset);
if (isInBox(x, y, test_x, test_y, test_x + (32 * offset), test_y + (32 * offset)))
return ToolbarSaveLoad;
test_x += (40 * offset);
if (isInBox(x, y, test_x, test_y, test_x + (32 * offset), test_y + (32 * offset)))
return ToolbarSkip;
test_x += (40 * offset);
if (isInBox(x, y, test_x, test_y, test_x + (32 * offset), test_y + (32 * offset)))
return ToolbarSound;
if (_gfx_mode_switch && !high_res) {
test_x += (40 * offset);
if (isInBox(x, y, test_x, test_y, test_x + (32 * offset), test_y + (32 * offset)))
return ToolbarMode;
}
return ToolbarNone;
}
/* ************************** BLT IMPLEMENTATION **************************** */
void beginBltPart() {
if (pBeginDraw)
pBeginDraw();
}
void endBltPart() {
if (pEndDraw)
pEndDraw();
}
void Blt(UBYTE * scr_ptr)
{
pBlt(scr_ptr);
//if (toolbar_available && currentScreenMode && !toolbar_drawn)
if (toolbar_available && !toolbar_drawn && !hide_toolbar)
drawAllToolbar();
}
void Blt_part(UBYTE * src_ptr, int x, int y, int width, int height, int pitch, bool check) {
if (toolbar_available && !toolbar_drawn && !hide_toolbar)
drawAllToolbar();
if (y > _geometry_h)
return;
if (y + height > _geometry_h)
height = _geometry_h - y;
pBlt_part(src_ptr, x, y, width, height, NULL, pitch, TRUE);
//if (check && (y > _geometry_h || (y + height) > _geometry_h)) {
// toolbar_drawn = false;
//}
}
void checkToolbar() {
if (toolbar_available && !toolbar_drawn && !hide_toolbar)
drawAllToolbar();
}
/* *************************** MONO DISPLAY ********************************* */
#define ADVANCE_PARTIAL(address, step) \
bitshift += gxdp.cBPP; \
if(bitshift >= 8) \
{ \
bitshift = 0; \
bitmask = (1<<gxdp.cBPP)-1; \
address += step; \
} \
else \
bitmask <<= gxdp.cBPP;
#define ADVANCE_REV_PARTIAL(address, step) \
bitshift -= gxdp.cBPP; \
if(bitshift < 0) \
{ \
bitshift = 8-gxdp.cBPP; \
bitmask = ((1<<gxdp.cBPP)-1)<<bitshift; \
address += step; \
} \
else \
bitmask >>= gxdp.cBPP;
void mono_Set_565(INT16 *buffer, int pitch, int x, int y, int width, int height) {
static UBYTE *scraddr;
static UBYTE *dst;
static long pixelstep;
static long linestep;
static UBYTE bitmask;
static int bitshift;
static long skipmask;
scraddr = (UBYTE*)dynamicGXBeginDraw();
pixelstep = geom[useMode].pixelstep;
linestep = (pixelstep > 0) ? -1 : 1;
skipmask = geom[useMode].xSkipMask;
bitshift = 0;
bitmask = (1<<gxdp.cBPP)-1;
if(scraddr)
{
int lines = 0;
int current = 0;
scraddr += geom[useMode].startoffset;
scraddr += y * linestep;
while(lines != height)
{
int i;
current = 0;
dst = scraddr;
/* skip non updated pixels for this line */
for (i=0; i < x; i++)
dst += pixelstep;
/* Turtle warning !!! */
for (i=0; i<width; i++) {
if (skipmask == 0xffffffff || (long)i & skipmask) {
*dst = ((*dst)&~bitmask)|(COLORCONVMONO(
RED_FROM_565(*(buffer + i)),
GREEN_FROM_565(*(buffer + i)),
BLUE_FROM_565(*(buffer + i))) << bitshift);
dst += pixelstep;
}
}
ADVANCE_PARTIAL(scraddr, linestep);
buffer += pitch;
lines++;
}
}
dynamicGXEndDraw();
}
void mono_Blt(UBYTE *src_ptr) {
mono_Blt_part(src_ptr, 0, 0, _geometry_w, _geometry_h, NULL, 0);
}
void mono_Blt_part(UBYTE * scr_ptr, int x, int y, int width, int height,
UBYTE * own_palette, int pitch, BOOL useCache)
{
// Mono blit routines contain good deal of voodoo
static UBYTE *src;
static UBYTE *dst;
static UBYTE *scraddr;
static UBYTE *scr_ptr_limit;
static UBYTE *src_limit;
static long pixelstep;
static long linestep;
static long skipmask;
// Special code is used to deal with packed pixels in monochrome mode
static UBYTE bitmask;
static int bitshift;
if(!active)
{
Sleep(100);
return;
}
/* Update screen mode, also thread protection by doing this */
if(useMode != currentScreenMode)
{
useMode = currentScreenMode;
pCls();
}
pixelstep = geom[useMode].pixelstep;
linestep = geom[useMode].linestep;
skipmask = geom[useMode].xSkipMask;
if (!useCache)
scraddr = (UBYTE*)dynamicGXBeginDraw();
else
scraddr = displayCache;
if(pixelstep)
{
// this will work on mono iPAQ and @migo, don't know about any others
linestep = (pixelstep > 0) ? -1 : 1;
bitshift = 0;
bitmask = (1<<gxdp.cBPP)-1;
if(scraddr)
{
scraddr += geom[useMode].startoffset;
scr_ptr += geom[useMode].sourceoffset;
//scr_ptr_limit = scr_ptr + geom[useMode].lineLimit;
//src_limit = scr_ptr + geom[useMode].xLimit;
/* Update offsets to the current line */
scraddr += y * linestep;
scr_ptr_limit = scr_ptr + (pitch ? pitch : width) * height;
src_limit = scr_ptr + width;
/*
if (scr_ptr_limit > scr_ptr + geom[useMode].lineLimit)
scr_ptr_limit = scr_ptr + geom[useMode].lineLimit;
*/
/* CMI rendering */
if (high_res && !own_palette && !extra_wide_screen) {
while(scr_ptr < scr_ptr_limit)
{
int i;
src = scr_ptr;
dst = scraddr;
/* skip non updated pixels for this line */
for (i=0; i < x; i++)
dst += pixelstep;
while(src < src_limit)
{
*dst = ((*dst)&~bitmask)|(pal[*src]<<bitshift);
dst += pixelstep;
src +=2;
}
ADVANCE_PARTIAL(scraddr, linestep);
scr_ptr += (pitch ? 2 * pitch : 2 * width);
src_limit += (pitch ? 2 * pitch : 2 * width);
}
}
else
/* Internal pixel loops */
if(skipmask == 3 && (smooth_filter) && gxdp.cBPP >= 4)
{
while(scr_ptr < scr_ptr_limit)
{
int i;
src = scr_ptr;
dst = scraddr;
/* skip non updated pixels for this line */
for (i=0; i < x; i++)
dst += pixelstep;
while(src < src_limit)
{
UBYTE r, g, b;
if (!own_palette) {
r = (3*palRed[*(src+0)] + palRed[*(src+1)])>>2;
g = (3*palGreen[*(src+0)] + palGreen[*(src+1)])>>2;
b = (3*palBlue[*(src+0)] + palBlue[*(src+1)])>>2;
} else {
r = (3 * own_palette[3 * *(src + 0)] +
own_palette[3 * *(src + 1)]) >> 2;
g = (3 * own_palette[3 * *(src + 0) + 1] +
own_palette[3 * *(src + 1) + 1]) >> 2;
b = (3 * own_palette[3 * *(src + 0) + 2] +
own_palette[3 * *(src + 1) + 2]) >> 2;
}
*dst = (*dst & ~bitmask) | (COLORCONVMONO(r,g,b)<<bitshift);
dst += pixelstep;
if (!own_palette) {
r = (palRed[*(src+1)] + palRed[*(src+2)])>>1;
g = (palGreen[*(src+1)] + palGreen[*(src+2)])>>1;
b = (palBlue[*(src+1)] + palBlue[*(src+2)])>>1;
}
else {
r = (own_palette[3 * *(src + 1)] +
own_palette[3 * *(src + 2)]) >> 2;
g = (own_palette[3 * *(src + 1) + 1] +
own_palette[3 * *(src + 2) + 1]) >> 2;
b = (own_palette[3 * *(src + 1) + 2] +
own_palette[3 * *(src + 2) + 2]) >> 2;
}
*dst = (*dst & ~bitmask) | (COLORCONVMONO(r,g,b)<<bitshift);
dst += pixelstep;
if (!own_palette) {
r = (palRed[*(src+2)] + 3*palRed[*(src+3)])>>2;
g = (palGreen[*(src+2)] + 3*palGreen[*(src+3)])>>2;
b = (palBlue[*(src+2)] + 3*palBlue[*(src+3)])>>2;
}
else {
r = (own_palette[3 * *(src + 2)] +
3 * own_palette[3 * *(src + 3)]) >> 2;
g = (own_palette[3 * *(src + 2) + 1] +
3 * own_palette[3 * *(src + 3) + 1]) >> 2;
b = (own_palette[3 * *(src + 2) + 2] +
3 * own_palette[3 * *(src + 3) + 2]) >> 2;
}
*dst = (*dst & ~bitmask) | (COLORCONVMONO(r,g,b)<<bitshift);
dst += pixelstep;
src += 4;
}
ADVANCE_PARTIAL(scraddr, linestep);
scr_ptr += (pitch ? pitch : width);
src_limit += (pitch ? pitch : width);
}
}
else if(skipmask != 0xffffffff)
{
while(scr_ptr < scr_ptr_limit)
{
int i;
src = scr_ptr;
dst = scraddr;
/* skip non updated pixels for this line */
for (i=0; i < x; i++)
dst += pixelstep;
while(src < src_limit)
{
if((long)src & skipmask)
{
if (!own_palette)
*dst = ((*dst)&~bitmask)|(pal[*src]<<bitshift);
else
*dst = ((*dst)&~bitmask)|(COLORCONVMONO(
own_palette[3 * *src],
own_palette[(3 * *src) + 1],
own_palette[(3 * *src) + 2]) << bitshift);
dst += pixelstep;
}
src ++;
}
ADVANCE_PARTIAL(scraddr, linestep);
scr_ptr += (pitch ? pitch : width);
src_limit += (pitch ? pitch : width);
}
}
else
{
while(scr_ptr < scr_ptr_limit)
{
int i;
src = scr_ptr;
dst = scraddr;
/* skip non updated pixels for this line */
for (i=0; i < x; i++)
dst += pixelstep;
while(src < src_limit)
{
if (!own_palette)
*dst = ((*dst)&~bitmask)|(pal[*src]<<bitshift);
else
*dst = ((*dst)&~bitmask)|(COLORCONVMONO(
own_palette[3 * *src],
own_palette[(3 * *src) + 1],
own_palette[(3 * *src) + 2]) << bitshift);
dst += pixelstep;
src ++;
}
ADVANCE_PARTIAL(scraddr, linestep);
scr_ptr += (pitch ? pitch : width);
src_limit += (pitch ? pitch : width);
}
}
}
}
else
{
// Filtering is not implemented in this mode. Not needed by current devices anyway
pixelstep = (linestep > 0) ? 1 : -1;
if(scraddr)
{
scraddr += geom[useMode].startoffset;
scr_ptr += geom[useMode].sourceoffset;
//scr_ptr_limit = scr_ptr + geom[useMode].lineLimit;
//src_limit = scr_ptr + geom[useMode].xLimit;
/* Update offsets to the current line */
scraddr += y * linestep;
scr_ptr_limit = scr_ptr + (pitch ? pitch : width) * height;
src_limit = scr_ptr + width;
if (scr_ptr_limit > scr_ptr + geom[useMode].lineLimit)
scr_ptr_limit = scr_ptr + geom[useMode].lineLimit;
/* CMI rendering */
if (high_res && !own_palette && !extra_wide_screen) {
if(pixelstep > 0)
{
bitshift = 8-gxdp.cBPP;
bitmask = ((1<<gxdp.cBPP)-1)<<bitshift;
while(scr_ptr < scr_ptr_limit)
{
int i;
src = scr_ptr;
dst = scraddr;
dst -= (linestep-pixelstep);
/* skip non updated pixels for this line */
for (i=0; i < x; i++)
ADVANCE_REV_PARTIAL(dst, pixelstep);
while(src < src_limit)
{
*dst = ((*dst)&~bitmask)|(pal[*src]<<bitshift);
ADVANCE_REV_PARTIAL(dst, pixelstep);
src += 2;
}
scraddr += linestep;
scr_ptr += (pitch ? 2 * pitch : 2 * width);
src_limit += (pitch ? 2 * pitch : 2 * width);
}
}
else {
bitshift = 0;
bitmask = (1<<gxdp.cBPP)-1;
while(scr_ptr < scr_ptr_limit)
{
int i;
src = scr_ptr;
dst = scraddr;
/* skip non updated pixels for this line */
for (i=0; i < x; i++)
ADVANCE_PARTIAL(dst, pixelstep);
while(src < src_limit)
{
*dst = ((*dst)&~bitmask)|(pal[*src]<<bitshift);
ADVANCE_PARTIAL(dst, pixelstep);
src += 2;
}
scraddr += linestep;
scr_ptr += (pitch ? 2 * pitch : 2 * width);
src_limit += (pitch ? 2 * pitch : 2 * width);
}
}
}
else
if(skipmask != 0xffffffff)
{
if(pixelstep > 0)
{
bitshift = 8-gxdp.cBPP;
bitmask = ((1<<gxdp.cBPP)-1)<<bitshift;
while(scr_ptr < scr_ptr_limit)
{
int i;
src = scr_ptr;
dst = scraddr;
dst -= (linestep-pixelstep);
/* skip non updated pixels for this line */
for (i=0; i < x; i++)
ADVANCE_REV_PARTIAL(dst, pixelstep);
while(src < src_limit)
{
if((long)src & skipmask)
{
if (!own_palette)
*dst = ((*dst)&~bitmask)|(pal[*src]<<bitshift);
else
*dst = ((*dst)&~bitmask)|(COLORCONVMONO(
own_palette[3 * *src],
own_palette[(3 * *src) + 1],
own_palette[(3 * *src) + 2]) << bitshift);
ADVANCE_REV_PARTIAL(dst, pixelstep);
}
src ++;
}
scraddr += linestep;
scr_ptr += (pitch ? pitch : width);
src_limit += (pitch ? pitch : width);
}
}
else
{
bitshift = 0;
bitmask = (1<<gxdp.cBPP)-1;
while(scr_ptr < scr_ptr_limit)
{
int i;
src = scr_ptr;
dst = scraddr;
/* skip non updated pixels for this line */
for (i=0; i < x; i++)
ADVANCE_PARTIAL(dst, pixelstep);
while(src < src_limit)
{
if((long)src & skipmask)
{
if (!own_palette)
*dst = ((*dst)&~bitmask)|(pal[*src]<<bitshift);
else
*dst = ((*dst)&~bitmask)|(COLORCONVMONO(
own_palette[3 * *src],
own_palette[(3 * *src) + 1],
own_palette[(3 * *src) + 2]) << bitshift);
ADVANCE_PARTIAL(dst, pixelstep);
}
src ++;
}
scraddr += linestep;
scr_ptr += (pitch ? pitch : width);
src_limit += (pitch ? pitch : width);
}
}
}
else
{
if(pixelstep > 0)
{
bitshift = 8-gxdp.cBPP;
bitmask = ((1<<gxdp.cBPP)-1)<<bitshift;
while(scr_ptr < scr_ptr_limit)
{
int i;
src = scr_ptr;
dst = scraddr;
dst -= (linestep-pixelstep);
/* skip non updated pixels for this line */
for (i=0; i < x; i++)
ADVANCE_REV_PARTIAL(dst, pixelstep);
while(src < src_limit)
{
if (!own_palette)
*dst = ((*dst)&~bitmask)|(pal[*src]<<bitshift);
else
*dst = ((*dst)&~bitmask)|(COLORCONVMONO(
own_palette[3 * *src],
own_palette[(3 * *src) + 1],
own_palette[(3 * *src) + 2]) << bitshift);
ADVANCE_REV_PARTIAL(dst, pixelstep);
src ++;
}
scraddr += linestep;
scr_ptr += (pitch ? pitch : width);
src_limit += (pitch ? pitch : width);
}
}
else
{
bitshift = 0;
bitmask = (1<<gxdp.cBPP)-1;
while(scr_ptr < scr_ptr_limit)
{
int i;
src = scr_ptr;
dst = scraddr;
/* skip non updated pixels for this line */
for (i=0; i < x; i++)
ADVANCE_PARTIAL(dst, pixelstep);
while(src < src_limit)
{
if (!own_palette)
*dst = ((*dst)&~bitmask)|(pal[*src]<<bitshift);
else
*dst = ((*dst)&~bitmask)|(COLORCONVMONO(
own_palette[3 * *src],
own_palette[(3 * *src) + 1],
own_palette[(3 * *src) + 2]) << bitshift);
ADVANCE_PARTIAL(dst, pixelstep);
src ++;
}
scraddr += linestep;
scr_ptr += (pitch ? pitch : width);
src_limit += (pitch ? pitch : width);
}
}
}
}
}
if (!useCache)
dynamicGXEndDraw();
}
/* *************************** PALETTED DISPLAY ********************************* */
void palette_Set_565(INT16 *buffer_param, int pitch, int x, int y, int width, int height) {
static UBYTE *scraddr;
static UBYTE *dst;
static long pixelstep;
static long linestep;
static long skipmask;
static unsigned char *color_match_2;
static UINT16 *buffer;
buffer = (UINT16*)buffer_param;
scraddr = (UBYTE*)dynamicGXBeginDraw();
pixelstep = geom[useMode].pixelstep;
linestep = geom[useMode].linestep;
skipmask = geom[useMode].xSkipMask;
color_match_2 = (unsigned char*)malloc(0xffff);
if (color_match_2)
memset(color_match_2, 0xff, 0xffff);
if(scraddr)
{
int lines = 0;
int current = 0;
scraddr += geom[useMode].startoffset;
scraddr += y * linestep;
while(lines != height)
{
int i;
current = 0;
dst = scraddr;
/* skip non updated pixels for this line */
for (i=0; i < x; i++)
dst += pixelstep;
/* Turtle warning !!! */
for (i=0; i<width; i++) {
if (skipmask == 0xffffffff || (long)i & skipmask) {
if (color_match_2) {
if (color_match_2[*(buffer + i)] == 255)
color_match_2[*(buffer + i)] = best_match(
RED_FROM_565(*(buffer + i)),
GREEN_FROM_565(*(buffer + i)),
BLUE_FROM_565(*(buffer + i)), 236) + 10;
*dst = color_match_2[*(buffer + i)];
}
else {
*dst = best_match(
RED_FROM_565(*(buffer + i)),
GREEN_FROM_565(*(buffer + i)),
BLUE_FROM_565(*(buffer + i)), 236) + 10;
}
dst += pixelstep;
}
}
buffer += pitch;
scraddr += linestep;
lines++;
}
}
if (color_match_2)
free(color_match_2);
dynamicGXEndDraw();
}
void palette_Blt(UBYTE *src_ptr) {
palette_Blt_part(src_ptr, 0, 0, _geometry_w, _geometry_h, NULL, 0);
}
void palette_Blt_part(UBYTE * scr_ptr,int x, int y, int width, int height,
UBYTE * own_palette, int pitch, BOOL useCache)
{
static UBYTE *src;
static UBYTE *dst;
static UBYTE *scraddr;
static UBYTE *scr_ptr_limit;
static UBYTE *src_limit;
static long pixelstep;
static long linestep;
static long skipmask;
// Special code is used to deal with packed pixels in monochrome mode
static UBYTE bitmask;
static int bitshift;
if(!active)
{
Sleep(100);
return;
}
/* Update screen mode, also thread protection by doing this */
if(useMode != currentScreenMode)
{
useMode = currentScreenMode;
pCls();
}
pixelstep = geom[useMode].pixelstep;
linestep = geom[useMode].linestep;
skipmask = geom[useMode].xSkipMask;
if (!useCache)
scraddr = (UBYTE*)dynamicGXBeginDraw();
else
scraddr = displayCache;
if(scraddr)
{
scraddr += geom[useMode].startoffset;
scr_ptr += geom[useMode].sourceoffset;
//scr_ptr_limit = scr_ptr + geom[useMode].lineLimit;
//src_limit = scr_ptr + geom[useMode].xLimit;
/* Update offsets to the current line */
scraddr += y * linestep;
scr_ptr_limit = scr_ptr + (pitch ? pitch : width) * height;
src_limit = scr_ptr + width;
/*
if (scr_ptr_limit > scr_ptr + geom[useMode].lineLimit)
scr_ptr_limit = scr_ptr + geom[useMode].lineLimit;
*/
/* CMI rendering */
if (high_res && !own_palette && !extra_wide_screen) {
while(scr_ptr < scr_ptr_limit)
{
int i;
src = scr_ptr;
dst = scraddr;
/* skip non updated pixels for this line */
for (i=0; i < x; i++)
dst += pixelstep;
while(src < src_limit)
{
if (*src < 236)
*dst = *src + 10;
else
*dst = staticTranslate[*src-236];
dst += pixelstep;
src += 2;
}
scraddr += linestep;
scr_ptr += (pitch ? 2 * pitch : 2 * width);
src_limit += (pitch ? 2 * pitch : 2 * width);
}
}
else
/* Internal pixel loops */
if(skipmask != 0xffffffff)
{
while(scr_ptr < scr_ptr_limit)
{
int i;
src = scr_ptr;
dst = scraddr;
/* skip non updated pixels for this line */
for (i=0; i < x; i++)
dst += pixelstep;
while(src < src_limit)
{
if((long)src & skipmask)
{
if (!own_palette) {
if (*src < 236)
*dst = *src + 10;
else
*dst = staticTranslate[*src-236];
} else {
// Turtle warning !!!
if (color_match[*src] == 255)
color_match[*src] =
best_match(own_palette[(3 * *src)],
own_palette[(3 * *src) + 1],
own_palette[(3 * *src) + 2], 236) + 10;
*dst = color_match[*src];
}
dst += pixelstep;
}
src ++;
}
scraddr += linestep;
scr_ptr += (pitch ? pitch : width);
src_limit += (pitch ? pitch : width);
}
}
else
{
while(scr_ptr < scr_ptr_limit)
{
int i;
src = scr_ptr;
dst = scraddr;
/* skip non updated pixels for this line */
for (i=0; i < x; i++)
dst += pixelstep;
while(src < src_limit)
{
if (!own_palette) {
if (*src < 236)
*dst = *src + 10;
else
*dst = staticTranslate[*src-236];
}
else {
// Turtle warning !!!
if (color_match[*src] == 255)
color_match[*src] =
best_match(own_palette[(3 * *src)],
own_palette[(3 * *src) + 1],
own_palette[(3 * *src) + 2], 236) + 10;
*dst = color_match[*src];
}
dst += pixelstep;
src ++;
}
scraddr += linestep;
scr_ptr += (pitch ? pitch : width);
src_limit += (pitch ? pitch : width);
}
}
if (!useCache)
dynamicGXEndDraw();
}
}
/* ********************************* 555 DISPLAY ********************************* */
void hicolor555_Set_565(INT16 *buffer, int pitch, int x, int y, int width, int height) {
static UBYTE *scraddr;
static UBYTE *dst;
static long pixelstep;
static long linestep;
static long skipmask;
scraddr = (UBYTE*)dynamicGXBeginDraw();
pixelstep = geom[useMode].pixelstep;
linestep = geom[useMode].linestep;
skipmask = geom[useMode].xSkipMask;
if(scraddr)
{
int lines = 0;
int current = 0;
scraddr += geom[useMode].startoffset;
scraddr += y * linestep;
while(lines != height)
{
int i;
current = 0;
dst = scraddr;
/* skip non updated pixels for this line */
for (i=0; i < x; i++)
dst += pixelstep;
/* Turtle warning !!! */
for (i=0; i<width; i++) {
if (skipmask == 0xffffffff || (long)i & skipmask) {
*(unsigned short*)dst = COLORCONV555(
RED_FROM_565(*(buffer + i)), GREEN_FROM_565(*(buffer + i)), BLUE_FROM_565(*(buffer + i))
);
dst += pixelstep;
}
}
buffer += pitch;
scraddr += linestep;
lines++;
}
}
dynamicGXEndDraw();
}
void hicolor555_Blt(UBYTE *src_ptr) {
hicolor555_Blt_part(src_ptr, 0, 0, _geometry_w, _geometry_h, NULL, 0);
}
void hicolor555_Blt_part(UBYTE * scr_ptr,int x, int y, int width, int height,
UBYTE * own_palette, int pitch, BOOL useCache)
{
static UBYTE *src;
static UBYTE *dst;
static UBYTE *scraddr;
static UBYTE *scr_ptr_limit;
static UBYTE *src_limit;
static long pixelstep;
static long linestep;
static long skipmask;
if(!active)
{
Sleep(100);
return;
}
/* Update screen mode, also thread protection by doing this */
if(useMode != currentScreenMode)
{
useMode = currentScreenMode;
pCls();
}
pixelstep = geom[useMode].pixelstep;
linestep = geom[useMode].linestep;
skipmask = geom[useMode].xSkipMask;
if (!useCache)
scraddr = (UBYTE*)dynamicGXBeginDraw();
else
scraddr = displayCache;
if(scraddr)
{
scraddr += geom[useMode].startoffset;
scr_ptr += geom[useMode].sourceoffset;
//scr_ptr_limit = scr_ptr + geom[useMode].lineLimit;
//src_limit = scr_ptr + geom[useMode].xLimit;
/* Update offsets to the current line */
scraddr += y * linestep;
scr_ptr_limit = scr_ptr + (pitch ? pitch : width) * height;
/*
if (scr_ptr_limit > scr_ptr + geom[useMode].lineLimit)
scr_ptr_limit = scr_ptr + geom[useMode].lineLimit;
*/
src_limit = scr_ptr + width;
/* CMI rendering */
if (high_res && !own_palette && !extra_wide_screen) {
while(scr_ptr < scr_ptr_limit)
{
int i;
src = scr_ptr;
dst = scraddr;
/* skip non updated pixels for this line */
for (i=0; i < x; i++)
dst += pixelstep;
while(src < src_limit)
{
UBYTE r, g, b;
/*
r = (3*palRed[*(src+0)] + palRed[*(src+1)])>>2;
g = (3*palGreen[*(src+0)] + palGreen[*(src+1)])>>2;
b = (3*palBlue[*(src+0)] + palBlue[*(src+1)])>>2;
*/
r = (2*palRed[*(src + 0)] + palRed[*(src + (pitch ? pitch : width) + 0)] + palRed[*(src + 1)]) >> 2;
g = (2*palGreen[*(src + 0)] + palGreen[*(src + (pitch ? pitch : width) + 0)] + palGreen[*(src + 1)]) >> 2;
b = (2*palBlue[*(src + 0)] + palBlue[*(src + (pitch ? pitch : width) + 0)] + palBlue[*(src + 1)]) >> 2;
*(unsigned short*)dst = COLORCONV555(r,g,b);
dst += pixelstep;
src += 2;
}
scraddr += linestep;
scr_ptr += (pitch ? 2 * pitch : 2 * width);
src_limit += (pitch ? 2 * pitch : 2 * width);
}
}
else
/* Internal pixel loops */
if(skipmask == 3 && smooth_filter)
{
while(scr_ptr < scr_ptr_limit)
{
int i;
src = scr_ptr;
dst = scraddr;
/* skip non updated pixels for this line */
for (i=0; i < x; i++)
dst += pixelstep;
while(src < src_limit)
{
UBYTE r, g, b;
if (!own_palette) {
r = (3*palRed[*(src+0)] + palRed[*(src+1)])>>2;
g = (3*palGreen[*(src+0)] + palGreen[*(src+1)])>>2;
b = (3*palBlue[*(src+0)] + palBlue[*(src+1)])>>2;
} else {
r = (3 * own_palette[3 * *(src + 0)] +
own_palette[3 * *(src + 1)]) >> 2;
g = (3 * own_palette[3 * *(src + 0) + 1] +
own_palette[3 * *(src + 1) + 1]) >> 2;
b = (3 * own_palette[3 * *(src + 0) + 2] +
own_palette[3 * *(src + 1) + 2]) >> 2;
}
*(unsigned short*)dst = COLORCONV555(r,g,b);
dst += pixelstep;
if (!own_palette) {
r = (palRed[*(src+1)] + palRed[*(src+2)])>>1;
g = (palGreen[*(src+1)] + palGreen[*(src+2)])>>1;
b = (palBlue[*(src+1)] + palBlue[*(src+2)])>>1;
}
else {
r = (own_palette[3 * *(src + 1)] +
own_palette[3 * *(src + 2)]) >> 2;
g = (own_palette[3 * *(src + 1) + 1] +
own_palette[3 * *(src + 2) + 1]) >> 2;
b = (own_palette[3 * *(src + 1) + 2] +
own_palette[3 * *(src + 2) + 2]) >> 2;
}
*(unsigned short*)dst = COLORCONV555(r,g,b);
dst += pixelstep;
if (!own_palette) {
r = (palRed[*(src+2)] + 3*palRed[*(src+3)])>>2;
g = (palGreen[*(src+2)] + 3*palGreen[*(src+3)])>>2;
b = (palBlue[*(src+2)] + 3*palBlue[*(src+3)])>>2;
}
else {
r = (own_palette[3 * *(src + 2)] +
3 * own_palette[3 * *(src + 3)]) >> 2;
g = (own_palette[3 * *(src + 2) + 1] +
3 * own_palette[3 * *(src + 3) + 1]) >> 2;
b = (own_palette[3 * *(src + 2) + 2] +
3 * own_palette[3 * *(src + 3) + 2]) >> 2;
}
*(unsigned short*)dst = COLORCONV555(r,g,b);
dst += pixelstep;
src += 4;
}
scraddr += linestep;
scr_ptr += (pitch ? pitch : width);
src_limit += (pitch ? pitch : width);
}
}
else if(skipmask != 0xffffffff)
{
while(scr_ptr < scr_ptr_limit)
{
int i;
src = scr_ptr;
dst = scraddr;
/* skip non updated pixels for this line */
for (i=0; i < x; i++)
dst += pixelstep;
while(src < src_limit)
{
if((long)src & skipmask)
{
if (!own_palette)
*(unsigned short*)dst = pal[*src];
else
*(unsigned short*)dst =
COLORCONV555(own_palette[3 * *src],
own_palette[(3 * *src) + 1],
own_palette[(3 * *src) + 2]);
dst += pixelstep;
}
src ++;
}
scraddr += linestep;
scr_ptr += (pitch ? pitch : width);
src_limit += (pitch ? pitch : width);
}
}
else
{
while(scr_ptr < scr_ptr_limit)
{
int i;
src = scr_ptr;
dst = scraddr;
/* skip non updated pixels for this line */
for (i=0; i < x; i++)
dst += pixelstep;
while(src < src_limit)
{
if (!own_palette)
*(unsigned short*)dst = pal[*src];
else
*(unsigned short*)dst =
COLORCONV555(own_palette[3 * *src],
own_palette[(3 * *src) + 1],
own_palette[(3 * *src) + 2]);
dst += pixelstep;
src ++;
}
scraddr += linestep;
scr_ptr += (pitch ? pitch : width);
src_limit += (pitch ? pitch : width);
}
}
if (!useCache)
dynamicGXEndDraw();
}
}
/* ********************************* 565 DISPLAY ********************************* */
void hicolor565_Blt(UBYTE *src_ptr) {
hicolor565_Blt_part(src_ptr, 0, 0, _geometry_w, _geometry_h, NULL, 0);
}
void hicolor565_Set_565(INT16 *buffer, int pitch, int x, int y, int width, int height) {
static UBYTE *scraddr;
static UBYTE *dst;
static long pixelstep;
static long linestep;
static long skipmask;
scraddr = (UBYTE*)dynamicGXBeginDraw();
pixelstep = geom[useMode].pixelstep;
linestep = geom[useMode].linestep;
skipmask = geom[useMode].xSkipMask;
if(scraddr)
{
int lines = 0;
int current = 0;
scraddr += geom[useMode].startoffset;
scraddr += y * linestep;
if (smartphone) {
while(lines != height)
{
int i;
current = 0;
dst = scraddr;
/* skip non updated pixels for this line */
dst += x * pixelstep;
for (i=0; i<width; i+=3) {
register UBYTE r,g,b;
register currentRed = RED_FROM_565(buffer[i]);
register currentGreen = GREEN_FROM_565(buffer[i]);
register currentBlue = BLUE_FROM_565(buffer[i]);
register currentRed1 = RED_FROM_565(buffer[i+1]);
register currentGreen1 = GREEN_FROM_565(buffer[i+1]);
register currentBlue1 = BLUE_FROM_565(buffer[i+1]);
register currentRed2 = RED_FROM_565(buffer[i+2]);
register currentGreen2 = GREEN_FROM_565(buffer[i+2]);
register currentBlue2 = BLUE_FROM_565(buffer[i+2]);
r = (3 * currentRed + currentRed1)>>2;
g = (3 * currentGreen + currentGreen1)>>2;
b = (3 * currentBlue + currentBlue1)>>2;
*(unsigned short*)dst = COLORCONV565(r, g, b);
dst += pixelstep;
r = (currentRed1 + currentRed2)>>1;
g = (currentGreen1 + currentGreen2)>>1;
b = (currentBlue1 + currentBlue2)>>1;
*(unsigned short*)dst = COLORCONV565(r, g, b);
dst += pixelstep;
}
buffer += pitch;
scraddr += linestep;
lines++;
if (lines != 0 && !(lines % 7)) {
lines++;
buffer += pitch;
}
}
}
else {
while(lines != height)
{
int i;
current = 0;
dst = scraddr;
/* skip non updated pixels for this line */
dst += x * pixelstep;
for (i=0; i<width; i++) {
if (skipmask == 0xffffffff || (long)i & skipmask) {
*(unsigned short*)dst = buffer[i];
dst += pixelstep;
}
}
//memcpy(dst, buffer, width * 2);
buffer += pitch;
scraddr += linestep;
lines++;
}
}
}
dynamicGXEndDraw();
}
int getColor565 (int color) {
return COLORCONV565(palRed[color], palGreen[color], palBlue[color]);
}
void hicolor565_Blt_part(UBYTE * scr_ptr, int x, int y, int width, int height,
UBYTE * own_palette, int pitch, BOOL useCache)
{
static UBYTE *src;
static UBYTE *dst;
static UBYTE *scraddr;
static UBYTE *scr_ptr_limit;
static UBYTE *src_limit;
static long pixelstep;
static long linestep;
static long skipmask;
if(!active)
{
Sleep(100);
return;
}
/* Update screen mode, also thread protection by doing this */
if(useMode != currentScreenMode)
{
useMode = currentScreenMode;
pCls();
}
pixelstep = geom[useMode].pixelstep;
linestep = geom[useMode].linestep;
skipmask = geom[useMode].xSkipMask;
if (!useCache)
scraddr = (UBYTE*)dynamicGXBeginDraw();
else
scraddr = displayCache;
if(scraddr)
{
scraddr += geom[useMode].startoffset;
scr_ptr += geom[useMode].sourceoffset;
//scr_ptr_limit = scr_ptr + geom[useMode].lineLimit;
//src_limit = scr_ptr + geom[useMode].xLimit;
/* Update offsets to the current line */
scraddr += y * linestep;
scr_ptr_limit = scr_ptr + (pitch ? pitch : width) * height;
/*
if (scr_ptr_limit > scr_ptr + geom[useMode].lineLimit)
scr_ptr_limit = scr_ptr + geom[useMode].lineLimit;
*/
src_limit = scr_ptr + width;
/* CMI rendering */
if (high_res && !own_palette && !extra_wide_screen) {
while(scr_ptr < scr_ptr_limit)
{
int i;
src = scr_ptr;
dst = scraddr;
/* skip non updated pixels for this line */
for (i=0; i < x; i++)
dst += pixelstep;
while(src < src_limit)
{
UBYTE r, g, b;
UBYTE *index1;
UBYTE *index2;
UBYTE *index3;
UBYTE *index4;
/*
r = (3*palRed[*(src+0)] + palRed[*(src+1)])>>2;
g = (3*palGreen[*(src+0)] + palGreen[*(src+1)])>>2;
b = (3*palBlue[*(src+0)] + palBlue[*(src+1)])>>2;
*/
r = (2*palRed[*(src + 0)] + palRed[*(src + (pitch ? pitch : width) + 0)] + palRed[*(src + 1)]) >> 2;
g = (2*palGreen[*(src + 0)] + palGreen[*(src + (pitch ? pitch : width) + 0)] + palGreen[*(src + 1)]) >> 2;
b = (2*palBlue[*(src + 0)] + palBlue[*(src + (pitch ? pitch : width) + 0)] + palBlue[*(src + 1)]) >> 2;
*(unsigned short*)dst = COLORCONV565(r,g,b);
dst += pixelstep;
src += 2;
}
scraddr += linestep;
scr_ptr += (pitch ? 2 * pitch : 2 * width);
src_limit += (pitch ? 2 * pitch : 2 * width);
}
}
else
/* Special Smartphone implementation */
/* Landscape mode, 2/3 X, 7/8 Y */
if (smartphone && own_palette) {
int line = 0;
int toskip = 0;
while(scr_ptr < scr_ptr_limit)
{
//int i;
src = scr_ptr;
dst = scraddr;
/* skip non updated pixels for this line */
//for (i=0; i < x; i++)
dst += x * pixelstep;
while(src < src_limit)
{
UBYTE r, g, b;
register first = 3 * *(src + 0);
register second = 3 * *(src + 1);
register third = 3 * *(src + 2);
r = (3 * own_palette[first] +
own_palette[second]) >> 2;
g = (3 * own_palette[first + 1] +
own_palette[second + 1]) >> 2;
b = (3 * own_palette[first + 2] +
own_palette[second + 2]) >> 2;
*(unsigned short*)dst = COLORCONV565(r,g,b);
dst += pixelstep;
r = (own_palette[second] +
own_palette[third]) >> 1;
g = (own_palette[second + 1] +
own_palette[third + 1]) >> 1;
b = (own_palette[second + 2] +
own_palette[third + 2]) >> 1;
*(unsigned short*)dst = COLORCONV565(r,g,b);
dst += pixelstep;
src += 3;
}
scraddr += linestep;
scr_ptr += (pitch ? pitch : width);
src_limit += (pitch ? pitch : width);
line++;
if (line == 7) {
scr_ptr += (pitch ? pitch : width);
src_limit += (pitch ? pitch : width);
line = 0;
}
}
}
else
if (smartphone && !own_palette) {
int line = 0;
int toskip = 0;
while(scr_ptr < scr_ptr_limit)
{
//int i;
src = scr_ptr;
dst = scraddr;
/* skip non updated pixels for this line */
//for (i=0; i < x; i++)
dst += x * pixelstep;
while(src < src_limit)
{
UBYTE r, g, b;
register first = *(src + 0);
register second = *(src + 1);
register third = *(src + 2);
if (line != 6) {
r = (3*palRed[first] + palRed[second])>>2;
g = (3*palGreen[first] + palGreen[second])>>2;
b = (3*palBlue[first] + palBlue[second])>>2;
}
else {
r = (2*palRed[first] + palRed[*(src + (pitch ? pitch : width) + 0)] + palRed[second]) >> 2;
g = (2*palGreen[first] + palGreen[*(src + (pitch ? pitch : width) + 0)] + palGreen[second]) >> 2;
b = (2*palBlue[first] + palBlue[*(src + (pitch ? pitch : width) + 0)] + palBlue[second]) >> 2;
}
*(unsigned short*)dst = COLORCONV565(r,g,b);
dst += pixelstep;
/*
r = (palRed[second] + palRed[third])>>1;
g = (palGreen[second] + palGreen[third])>>1;
b = (palBlue[second] + palBlue[third])>>1;
*(unsigned short*)dst = COLORCONV565(r,g,b);
dst += pixelstep;
*/
if (line != 6) {
r = (3*palRed[second] + palRed[third])>>2;
g = (3*palGreen[second] + palGreen[third])>>2;
b = (3*palBlue[second] + palBlue[third])>>2;
}
else {
r = (2*palRed[second] + palRed[*(src + 1 + (pitch ? pitch : width) + 0)] + palRed[third]) >> 2;
g = (2*palGreen[second] + palGreen[*(src + 1 + (pitch ? pitch : width) + 0)] + palGreen[third]) >> 2;
b = (2*palBlue[second] + palBlue[*(src + 1 + (pitch ? pitch : width) + 0)] + palBlue[third]) >> 2;
}
*(unsigned short*)dst = COLORCONV565(r,g,b);
dst += pixelstep;
src += 3;
}
scraddr += linestep;
scr_ptr += (pitch ? pitch : width);
src_limit += (pitch ? pitch : width);
line++;
if (line == 7) {
scr_ptr += (pitch ? pitch : width);
src_limit += (pitch ? pitch : width);
line = 0;
}
}
}
else
/* Internal pixel loops */
if(skipmask == 3 && smooth_filter)
{
while(scr_ptr < scr_ptr_limit)
{
int i;
src = scr_ptr;
dst = scraddr;
/* skip non updated pixels for this line */
for (i=0; i < x; i++)
dst += pixelstep;
while(src < src_limit)
{
UBYTE r, g, b;
if (!own_palette) {
r = (3*palRed[*(src+0)] + palRed[*(src+1)])>>2;
g = (3*palGreen[*(src+0)] + palGreen[*(src+1)])>>2;
b = (3*palBlue[*(src+0)] + palBlue[*(src+1)])>>2;
} else {
r = (3 * own_palette[3 * *(src + 0)] +
own_palette[3 * *(src + 1)]) >> 2;
g = (3 * own_palette[3 * *(src + 0) + 1] +
own_palette[3 * *(src + 1) + 1]) >> 2;
b = (3 * own_palette[3 * *(src + 0) + 2] +
own_palette[3 * *(src + 1) + 2]) >> 2;
}
*(unsigned short*)dst = COLORCONV565(r,g,b);
dst += pixelstep;
if (!own_palette) {
r = (palRed[*(src+1)] + palRed[*(src+2)])>>1;
g = (palGreen[*(src+1)] + palGreen[*(src+2)])>>1;
b = (palBlue[*(src+1)] + palBlue[*(src+2)])>>1;
}
else {
r = (own_palette[3 * *(src + 1)] +
own_palette[3 * *(src + 2)]) >> 1;
g = (own_palette[3 * *(src + 1) + 1] +
own_palette[3 * *(src + 2) + 1]) >> 1;
b = (own_palette[3 * *(src + 1) + 2] +
own_palette[3 * *(src + 2) + 2]) >> 1;
}
*(unsigned short*)dst = COLORCONV565(r,g,b);
dst += pixelstep;
if (!own_palette) {
r = (palRed[*(src+2)] + 3*palRed[*(src+3)])>>2;
g = (palGreen[*(src+2)] + 3*palGreen[*(src+3)])>>2;
b = (palBlue[*(src+2)] + 3*palBlue[*(src+3)])>>2;
}
else {
r = (own_palette[3 * *(src + 2)] +
3 * own_palette[3 * *(src + 3)]) >> 2;
g = (own_palette[3 * *(src + 2) + 1] +
3 * own_palette[3 * *(src + 3) + 1]) >> 2;
b = (own_palette[3 * *(src + 2) + 2] +
3 * own_palette[3 * *(src + 3) + 2]) >> 2;
}
*(unsigned short*)dst = COLORCONV565(r,g,b);
dst += pixelstep;
src += 4;
}
scraddr += linestep;
scr_ptr += (pitch ? pitch : width);
src_limit += (pitch ? pitch : width);
}
}
else if(skipmask != 0xffffffff)
{
int line = 0;
int toskip = 0;
while(scr_ptr < scr_ptr_limit)
{
int i;
src = scr_ptr;
dst = scraddr;
/* skip non updated pixels for this line */
for (i=0; i < x; i++)
dst += pixelstep;
while(src < src_limit)
{
if((long)src & skipmask)
{
if (!own_palette)
*(unsigned short*)dst = pal[*src];
else
*(unsigned short*)dst =
COLORCONV565(own_palette[3 * *src],
own_palette[(3 * *src) + 1],
own_palette[(3 * *src) + 2]);
dst += pixelstep;
}
src ++;
}
scraddr += linestep;
scr_ptr += (pitch ? pitch : width);
src_limit += (pitch ? pitch : width);
}
}
else
{
while(scr_ptr < scr_ptr_limit)
{
int i;
src = scr_ptr;
dst = scraddr;
/* skip non updated pixels for this line */
for (i=0; i < x; i++)
dst += pixelstep;
while(src < src_limit)
{
if (!own_palette)
*(unsigned short*)dst = pal[*src];
else
*(unsigned short*)dst =
COLORCONV565(own_palette[3 * *src],
own_palette[(3 * *src) + 1],
own_palette[(3 * *src) + 2]);
dst += pixelstep;
src ++;
}
scraddr += linestep;
scr_ptr += (pitch ? pitch : width);
src_limit += (pitch ? pitch : width);
}
}
if (!useCache)
dynamicGXEndDraw();
}
}
/* ********************************* NO GAPI DISPLAY ********************************* */
#ifndef NEW_GAPI_CODE
void noGAPI_Cls() {
HBITMAP old;
RECT rc;
HDC hdc = GetDC(hWndMain);
HBITMAP hb;
GetWindowRect(hWndMain, &rc);
memset(noGAPI_video_buffer, 0x00, sizeof(noGAPI_video_buffer));
if (currentScreenMode || wide_screen)
hb = CreateBitmap(320, 240, 1, 16, noGAPI_video_buffer);
else
hb = CreateBitmap(240, 320, 1, 16, noGAPI_video_buffer);
old = (HBITMAP)SelectObject(noGAPI_compat, hb);
if (currentScreenMode || wide_screen)
BitBlt(hdc, 0, 0, 320, 240, noGAPI_compat, 0, 0, SRCCOPY);
else
BitBlt(hdc, 0, 0, 240, 320, noGAPI_compat, 0, 0, SRCCOPY);
SelectObject(noGAPI_compat, old);
ReleaseDC(hWndMain, hdc);
DeleteObject(hb);
}
void noGAPI_Blt(UBYTE *src_ptr) {
noGAPI_Blt_part(src_ptr, 0, 0, _geometry_w, _geometry_h, NULL, 0);
}
void noGAPI_Set_565(INT16 *buffer, int pitch, int x, int y, int width, int height) {
HBITMAP old;
RECT rc;
HDC hdc = GetDC(hWndMain);
HBITMAP hb;
UBYTE *work_buffer;
int i;
int j;
//long skipmask;
//skipmask = geom[useMode].xSkipMask;
GetWindowRect(hWndMain, &rc);
work_buffer = noGAPI_video_buffer;
unsigned short *work_buffer_2 = (unsigned short*)work_buffer;
if (currentScreenMode && !wide_screen) {
for (i=0; i<width; i++) {
for (j=0; j<height; j++) {
work_buffer_2[i * height + j] =
buffer[(pitch ? pitch : width) * j + (width - i)];
}
}
}
else {
for (i=0; i<height; i++) {
for (j=0; j<width; j++) {
*(unsigned short*)work_buffer = buffer[(pitch ? pitch : width) * i + j];
work_buffer += 2;
}
}
}
if (currentScreenMode && !wide_screen)
hb = CreateBitmap(height, width, 1, 16, noGAPI_video_buffer);
else
hb = CreateBitmap(width, height, 1, 16, noGAPI_video_buffer);
old = (HBITMAP)SelectObject(noGAPI_compat, hb);
if (currentScreenMode && !wide_screen)
BitBlt(hdc, y , 320 - (x + width), height, width, noGAPI_compat, 0, 0, SRCCOPY);
else
BitBlt(hdc, x, y, width, height, noGAPI_compat, 0, 0, SRCCOPY);
SelectObject(noGAPI_compat, old);
ReleaseDC(hWndMain, hdc);
DeleteObject(hb);
}
void noGAPI_Blt_part(UBYTE * scr_ptr, int x, int y, int width, int height,
UBYTE * own_palette, int pitch, BOOL useCache) {
HBITMAP old;
RECT rc;
HDC hdc = GetDC(hWndMain);
HBITMAP hb;
UBYTE *work_buffer;
int i;
int j;
//long skipmask;
//skipmask = geom[useMode].xSkipMask;
GetWindowRect(hWndMain, &rc);
work_buffer = noGAPI_video_buffer;
if (currentScreenMode && !wide_screen) {
unsigned short *work_buffer_2 = (unsigned short*)work_buffer;
for (i=0; i<width; i++)
for (j=0; j<height; j++)
if (!own_palette)
work_buffer_2[i * height + j] =
pal[scr_ptr[(pitch ? pitch : width) * j + (width - i)]];
else
work_buffer_2[i * height + j] =
COLORCONV565(own_palette[3 * scr_ptr[(pitch ? pitch : width) * j + (width - i)]],
own_palette[(3 * scr_ptr[(pitch ? pitch : width) * j + (width - i)]) + 1],
own_palette[(3 * scr_ptr[(pitch ? pitch : width) * j + (width - i)]) + 2]);
}
else {
for (i=0; i<height; i++) {
for (j=0; j<width; j++) {
if (!own_palette)
*(unsigned short*)work_buffer =
pal[scr_ptr[(pitch ? pitch : width) * i + j]];
else
*(unsigned short*)work_buffer =
COLORCONV565(own_palette[3 * scr_ptr[(pitch ? pitch : width) * i + j]],
own_palette[(3 * scr_ptr[(pitch ? pitch : width) * i + j]) + 1],
own_palette[(3 * scr_ptr[(pitch ? pitch : width) * i + j]) + 2]);
work_buffer += 2;
}
}
}
if (currentScreenMode && !wide_screen)
hb = CreateBitmap(height, width, 1, 16, noGAPI_video_buffer);
else
hb = CreateBitmap(width, height, 1, 16, noGAPI_video_buffer);
old = (HBITMAP)SelectObject(noGAPI_compat, hb);
if (currentScreenMode && !wide_screen)
BitBlt(hdc, y , 320 - (x + width), height, width, noGAPI_compat, 0, 0, SRCCOPY);
else
BitBlt(hdc, x, y, width, height, noGAPI_compat, 0, 0, SRCCOPY);
SelectObject(noGAPI_compat, old);
ReleaseDC(hWndMain, hdc);
DeleteObject(hb);
}
#else
void noGAPI_Cls() {
HBITMAP old;
RECT rc;
HDC hdc = GetDC(hWndMain);
HBITMAP hb;
memset(noGAPI_buffer, 0x00, GetSystemMetrics(SM_CXSCREEN) * GetSystemMetrics(SM_CYSCREEN) * 3);
BitBlt(hdc, 0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN), noGAPI_compat, 0, 0, SRCCOPY);
ReleaseDC(hWndMain, hdc);
}
void noGAPI_Blt(UBYTE *src_ptr) {
noGAPI_Blt_part(src_ptr, 0, 0, _geometry_w, _geometry_h, NULL, 0);
}
void noGAPI_Set_565(INT16 *buffer, int pitch, int x, int y, int width, int height) {
HBITMAP old;
RECT rc;
HDC hdc = GetDC(hWndMain);
HBITMAP hb;
UBYTE *workBuffer = noGAPI_buffer;
INT16 *srcBuffer = buffer;
UBYTE *tempBuffer;
INT16 *tempSrcBuffer;
int i;
int j;
int startOffset;
int lineStep;
int pixelStep;
if (currentScreenMode && !wide_screen) {
startOffset = (GetSystemMetrics(SM_CXSCREEN) * (GetSystemMetrics(SM_CYSCREEN) - 1)) * 3;
lineStep = 3;
pixelStep = -(GetSystemMetrics(SM_CXSCREEN) * 3);
}
else {
startOffset = 0;
lineStep = GetSystemMetrics(SM_CXSCREEN) * 3;
pixelStep = 3;
}
workBuffer += startOffset;
workBuffer += y * lineStep;
for (i=0; i<height; i++) {
tempBuffer = workBuffer;
tempSrcBuffer = srcBuffer;
tempBuffer += x * pixelStep;
for (j=0; j<width; j++) {
*tempBuffer = BLUE_FROM_565(*tempSrcBuffer);
*(tempBuffer + 1) = GREEN_FROM_565(*tempSrcBuffer);
*(tempBuffer + 2) = RED_FROM_565(*tempSrcBuffer);
tempBuffer += pixelStep;
tempSrcBuffer++;
}
workBuffer += lineStep;
srcBuffer += (pitch ? pitch : width);
}
if (currentScreenMode && !wide_screen)
BitBlt(hdc, y , 320 - (x + width), height, width, noGAPI_compat, y, 320 - (x + width), SRCCOPY);
else
BitBlt(hdc, x, y, width, height, noGAPI_compat, x, y, SRCCOPY);
ReleaseDC(hWndMain, hdc);
}
void noGAPI_Blt_part(UBYTE * scr_ptr, int x, int y, int width, int height,
UBYTE * own_palette, int pitch, BOOL useCache) {
HDC hdc = GetDC(hWndMain);
HBITMAP hb;
UBYTE *workBuffer = noGAPI_buffer;
UBYTE *srcBuffer = scr_ptr;
UBYTE *tempBuffer;
UBYTE *tempSrcBuffer;
int i;
int j;
//long skipmask;
int startOffset;
int lineStep;
int pixelStep;
if (currentScreenMode && !wide_screen) {
startOffset = (GetSystemMetrics(SM_CXSCREEN) * (GetSystemMetrics(SM_CYSCREEN) - 1)) * 3;
lineStep = 3;
pixelStep = -(GetSystemMetrics(SM_CXSCREEN) * 3);
}
else {
startOffset = 0;
lineStep = GetSystemMetrics(SM_CXSCREEN) * 3;
pixelStep = 3;
}
if (high_res && !extra_wide_screen) {
height /= 2;
width /= 2;
}
workBuffer += startOffset;
workBuffer += y * lineStep;
for (i=0; i<height; i++) {
tempBuffer = workBuffer;
tempSrcBuffer = srcBuffer;
tempBuffer += x * pixelStep;
for (j=0; j<width; j++) {
if (!own_palette) {
if (high_res && !extra_wide_screen) {
*tempBuffer = (3*palBlue[*tempSrcBuffer] + palBlue[*(tempSrcBuffer + 1)]) >> 2;
*(tempBuffer + 1) = (3 * palGreen[*tempSrcBuffer] + palGreen[(*tempSrcBuffer + 1)]) >> 2;
*(tempBuffer + 2) = (3 * palRed[*tempSrcBuffer] + palRed[*(tempSrcBuffer + 1)]) >> 2;
tempBuffer += pixelStep;
tempSrcBuffer += 2;
}
else {
*tempBuffer = palBlue[*tempSrcBuffer];
*(tempBuffer + 1) = palGreen[*tempSrcBuffer];
*(tempBuffer + 2) = palRed[*tempSrcBuffer];
tempBuffer += pixelStep;
tempSrcBuffer++;
}
}
else {
*tempBuffer = own_palette[3 * *tempSrcBuffer + 2];
*(tempBuffer + 1) = own_palette[3 * *tempSrcBuffer + 1];
*(tempBuffer + 2) = own_palette[3 * *tempSrcBuffer];
tempBuffer += pixelStep;
tempSrcBuffer++;
}
}
workBuffer += lineStep;
if (high_res && !extra_wide_screen)
srcBuffer += (pitch ? 2 * pitch : 2 * width);
else
srcBuffer += (pitch ? pitch : width);
}
if (currentScreenMode && !wide_screen)
BitBlt(hdc, y , 320 - (x + width), height, width, noGAPI_compat, y, 320 - (x + width), SRCCOPY);
else
BitBlt(hdc, x, y, width, height, noGAPI_compat, x, y, SRCCOPY);
ReleaseDC(hWndMain, hdc);
}
#endif
/* ************************** STYLUS TRANSLATION ************************* */
void Translate(int* px, int* py)
{
int x, y;
if ((wide_screen && !high_res) || (wide_screen && extra_wide_screen && high_res))
return;
if (wide_screen && high_res) {
if (!g_gui->isActive()) {
*px = *px * 2;
*py = *py * 2;
}
return;
}
if (high_res) {
x = 320 - *py;
y = *px;
if (!g_gui->isActive()) {
*px = x * 2;
*py = y * 2;
}
else {
*px = x;
*py = y;
}
return;
}
switch(currentScreenMode)
{
case 0: /* portrait */
*px = *px*4/3;
break;
case 1: /* landscape left */
x = 320 - *py;
y = *px;
*px = x;
*py = y;
break;
case 2: /* landscape right */
x = *py;
y = 240 - *px;
*px = x;
*py = y;
break;
}
}
/* ************************** LAUNCHER FONT STUFF ************************* */
void printChar(const char str, int xx, int yy, int textcolor, int highlight, int width)
{
unsigned int buffer = 0, mask = 0, x, y;
byte *tmp;
byte *ptr;
tmp = &textfont[0];
tmp += 224 + (str + 1) * 8;
ptr = decomp + (yy * width) + xx;
for (y = 0; y < 8; y++) {
for (x = 0; x < 8; x++) {
unsigned char color;
if ((mask >>= 1) == 0) {
buffer = *tmp++;
mask = 0x80;
}
color = ((buffer & mask) != 0);
if (color)
ptr[x] = textcolor;
else if (highlight > 0)
ptr[x] = highlight;
}
if (highlight > 0) {
int i;
for (i=9; i<width; i++)
ptr[x] = highlight;
}
ptr += width;
}
}
void printString(const char *str, int x, int y, int textcolor, int highlight, int width)
{
for (uint letter = 0; letter < strlen(str); letter++)
printChar(str[letter], x + (letter * 8), y, textcolor, highlight, width);
}
#define MAX_CHARS_PER_LINE 29
int drawString(const char *str, int x, int y, int textcolor, int highlight) {
int current_y;
unsigned int current_pos = 0;
char substring[MAX_CHARS_PER_LINE + 1];
current_y = y;
while(current_pos < strlen(str)) {
memset(decomp + (current_y * 320), 0, 320 * 8);
memset(substring, 0, sizeof(substring));
if (strlen(str + current_pos) > MAX_CHARS_PER_LINE)
memcpy(substring, str + current_pos, MAX_CHARS_PER_LINE);
else
strcpy(substring, str + current_pos);
printString(substring, x, current_y, textcolor, highlight, 320);
pBlt_part(decomp + (current_y * 320), 0, current_y, 320, 8, item_startup_colors, 0);
current_pos += MAX_CHARS_PER_LINE;
current_y += 10;
}
return current_y;
}
/* ************************** DIRECT BLT IMPLEMENTATION ************************* */
void Get_565(UBYTE *src, INT16 *buffer, int pitch, int x, int y, int width, int height) {
int i,j;
UBYTE *tempo = (UBYTE*)buffer;
// Dumb conversion to 565
if (!(high_res && !wide_screen)) {
for (i=0; i<height; i++) {
for (j=0; j<width; j++) {
*buffer++ = COLORCONV565(palRed[*src], palGreen[*src], palBlue[*src]);
src++;
}
}
}
else {
UBYTE *current;
for (i=0; i<height; i++) {
current = src;
for (j=0; j<width; j++) {
*buffer++ = COLORCONV565(palRed[*current], palGreen[*current], palBlue[*current]);
current += 2;
}
src += 2 * 640;
}
}
}
void Set_565(INT16 *buffer, int pitch, int x, int y, int width, int height) {
pSet_565(buffer, pitch, x, y, width, height);
}
void NULL_Set_565(INT16 *buffer, int pitch, int x, int y, int width, int height) {
}
#endif