mirror of
https://github.com/libretro/scummvm.git
synced 2025-01-05 09:10:29 +00:00
b72df416a6
CVS. Though it has some issues unresolved, one of them is that it crashes right after splash screen without showing anything. Work in progress :) svn-id: r17054
3222 lines
80 KiB
C++
3222 lines
80 KiB
C++
/* ScummVM - Scumm Interpreter
|
|
* Copyright (C) 2001 Ludvig Strigeus
|
|
* Copyright (C) 2001/2004 The ScummVM project
|
|
* Copyright (C) 2002 Ph0x - GP32 Backend
|
|
* Copyright (C) 2003/2004 DJWillis - GP32 Backend
|
|
*
|
|
* 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$
|
|
*
|
|
*/
|
|
|
|
/*
|
|
*
|
|
* Main Source for ScummVM for the GP32
|
|
*
|
|
*/
|
|
|
|
// TODO:
|
|
// Clean up GP leftovers and strip backend to only bits the GP32 needs.
|
|
// Finish restructure.
|
|
// Sort all remaining GCC 3.4 warnings.
|
|
// setTimerCallback: function call doesnt use * ?
|
|
|
|
//#define REAL_MAIN
|
|
|
|
#ifdef GP32_GDB
|
|
#include <gdb-stub.h>
|
|
#endif /*GP32_GDB */
|
|
|
|
#include "backends/gp32/setup.h"
|
|
|
|
#include "backends/gp32/gp32.h"
|
|
|
|
#include "backends/gp32/gfx_splash.h"
|
|
//#include "backends/gp32/resources/gfx_splash_alt.h"
|
|
|
|
#define gpRGB16(r,g,b) (((((r)>>3)&0x1F) << 11) | ((((g)>>3)&0x1F) << 6) | (((b)>>3)&0x1F)<<1)
|
|
#define RGB_TO_16(r,g,b) (((((r)>>3)&0x1F) << 11) | ((((g)>>3)&0x1F) << 6) | (((b)>>3)&0x1F)<<1)
|
|
|
|
int nflip, keydata; // Flip Index
|
|
GP_HPALETTE PAL; //palette
|
|
GPDRAWSURFACE LCDbuffer[BUFFERCOUNT + 1]; //buffers
|
|
|
|
void GpSetPaletteEntry(u8 i, u8 r, u8 g, u8 b);
|
|
|
|
// FIXME: No global init!
|
|
|
|
float gammatab[256], gammatab2[256]; // fixme: one table
|
|
const float scrGamma[] = { 1.0, 1.001, 1.002, 1.003, 1.004, 1.005 };
|
|
char gindex = 3;
|
|
|
|
int mx = 1, my = 1;
|
|
int scrofsy = 239;
|
|
char currentsurf;
|
|
|
|
// FIXME!!
|
|
// crashes if here and not buildgammatab() not called as very first line! check
|
|
// check if sav file handling overwrites something!
|
|
// float gammatab[256];
|
|
|
|
FILE *fstderr, *fstdout, *fstdin;
|
|
|
|
/****************************************************************
|
|
GP32 Input mappings - Returns Button Pressed.
|
|
****************************************************************/
|
|
int gpTrapKey(void)
|
|
{
|
|
int value = 0;
|
|
|
|
#define rKEY_A 0x4000
|
|
#define rKEY_B 0x2000
|
|
#define rKEY_L 0x1000
|
|
#define rKEY_R 0x8000
|
|
#define rKEY_UP 0x0800
|
|
#define rKEY_DOWN 0x0200
|
|
#define rKEY_LEFT 0x0100
|
|
#define rKEY_RIGHT 0x0400
|
|
#define rKEY_START 0x0040
|
|
#define rKEY_SELECT 0x0080
|
|
#define rPBDAT (*(volatile unsigned *)0x1560000c)
|
|
#define rPEDAT (*(volatile unsigned *)0x15600030)
|
|
|
|
unsigned long gpb = rPBDAT; // 0x156
|
|
unsigned long gpe = rPEDAT;
|
|
|
|
if ((gpb & rKEY_LEFT) == 0)
|
|
value |= GPC_VK_LEFT;
|
|
if ((gpb & rKEY_RIGHT) == 0)
|
|
value |= GPC_VK_RIGHT;
|
|
if ((gpb & rKEY_UP) == 0)
|
|
value |= GPC_VK_UP;
|
|
if ((gpb & rKEY_DOWN) == 0)
|
|
value |= GPC_VK_DOWN;
|
|
if ((gpb & rKEY_A) == 0)
|
|
value |= GPC_VK_FA;
|
|
if ((gpb & rKEY_B) == 0)
|
|
value |= GPC_VK_FB;
|
|
if ((gpb & rKEY_L) == 0)
|
|
value |= GPC_VK_FL;
|
|
if ((gpb & rKEY_R) == 0)
|
|
value |= GPC_VK_FR;
|
|
if ((gpe & rKEY_SELECT) == 0)
|
|
value |= GPC_VK_SELECT;
|
|
if ((gpe & rKEY_START) == 0)
|
|
value |= GPC_VK_START;
|
|
|
|
return value;
|
|
}
|
|
|
|
/****************************************************************
|
|
GP32 ScummVM OSystem Implementation.
|
|
****************************************************************/
|
|
|
|
//OSystem *OSystem_GP32::create()
|
|
//{
|
|
// //OSystem_GP32 *syst = new OSystem_GP32();
|
|
// //return syst;
|
|
// return new OSystem_GP32();
|
|
//}
|
|
|
|
OSystem *OSystem_GP32_create()
|
|
{
|
|
//
|
|
// OSystem_GP32 *syst = new OSystem_GP32();
|
|
////
|
|
//// //syst->_mode = gfx_mode;
|
|
//// //syst->_full_screen = full_screen;
|
|
//
|
|
// // allocate palette storage
|
|
// syst->_currentPalette = (gpColor*)calloc(sizeof(gpColor), 256);
|
|
//
|
|
// // allocate the dirty rect storage
|
|
// syst->_mouseBackup = (byte*)malloc(MAX_MOUSE_W * MAX_MOUSE_H * MAX_SCALING * 2);
|
|
// return syst;
|
|
// return new OSystem_GP32();
|
|
|
|
//return OSystem_GP32::create();
|
|
return new OSystem_GP32();
|
|
}
|
|
|
|
OSystem_GP32::OSystem_GP32() :
|
|
//#ifdef USE_OSD
|
|
// _osdSurface(0), _osdAlpha(SDL_ALPHA_TRANSPARENT), _osdFadeStartTime(0),
|
|
//#endif
|
|
_hwscreen(0), _screen(0), _screenWidth(0), _screenHeight(0),
|
|
_tmpscreen(0), _overlayVisible(false),
|
|
// _cdrom(0),
|
|
// _scaler_proc(0),
|
|
_modeChanged(false), _dirty_checksums(0),
|
|
_mouseVisible(false), _mouseDrawn(false), _mouseData(0),
|
|
_mouseHotspotX(0), _mouseHotspotY(0),
|
|
_currentShakePos(0), _newShakePos(0),
|
|
_paletteDirtyStart(0), _paletteDirtyEnd(0), _graphicsMutex(0) {
|
|
|
|
// allocate palette storage
|
|
_currentPalette = (gpColor *) calloc(sizeof(gpColor), 256);
|
|
|
|
// allocate the dirty rect storage
|
|
_mouseBackup =
|
|
(byte *) malloc(MAX_MOUSE_W * MAX_MOUSE_H * MAX_SCALING * 2);
|
|
|
|
// reset mouse state
|
|
memset(&km, 0, sizeof(km));
|
|
|
|
_scaleFactor = 1;
|
|
_scaler_proc = Normal1x;
|
|
|
|
_mode = GFX_NORMAL;
|
|
_full_screen = true;
|
|
_adjustAspectRatio = false;
|
|
_mode_flags = 0;
|
|
|
|
//init_intern();
|
|
}
|
|
|
|
OSystem_GP32::~OSystem_GP32() {
|
|
if (_dirty_checksums)
|
|
free(_dirty_checksums);
|
|
free(_currentPalette);
|
|
free(_mouseBackup);
|
|
deleteMutex(_graphicsMutex);
|
|
quit();
|
|
}
|
|
|
|
// Set colors of the palette
|
|
void OSystem_GP32::setPalette(const byte * colors, uint start, uint num) {
|
|
const byte *b = colors;
|
|
uint i;
|
|
gpColor *base = _currentPalette + start;
|
|
for (i = 0; i < num; i++) {
|
|
base[i].r = b[0];
|
|
base[i].g = b[1];
|
|
base[i].b = b[2];
|
|
b += 4;
|
|
}
|
|
|
|
if (start < _paletteDirtyStart)
|
|
_paletteDirtyStart = start;
|
|
|
|
if (start + num > _paletteDirtyEnd)
|
|
_paletteDirtyEnd = start + num;
|
|
}
|
|
|
|
// Set the size of the video bitmap.
|
|
// Typically, 320x200 (x240 for FMTowns)
|
|
|
|
// FIXME: Is there a clean way to get the Game_ID in the backend, I still like the virual keymap feature below.
|
|
//#include "base/gameDetector.h"
|
|
//#include "scumm/scumm.h"
|
|
//extern ScummEngine *g_scumm;
|
|
|
|
const char shortkey0[] = "";
|
|
const char shortkey1[] = "gpuolscty"; // give, pick up, use, open, look at, push, close, talk to, pull
|
|
const char shortkey2[] = "qwerasdfzxcv"; //push, open, walk to, use, pull, close, pick up, turn on, give, look, what is, turn off
|
|
const char shortkey3[] = "wlptuo"; // samnmax
|
|
const char *shortkey;
|
|
int skindex = 0;
|
|
|
|
void OSystem_GP32::initSize(uint w, uint h) {
|
|
/*switch (menu[MENU_SCREENPOS].index) {
|
|
* case 0 : scrofsy = 239 - (240 - h)/2; break;
|
|
* case 1 : scrofsy = 239; break;
|
|
* }
|
|
*/
|
|
//switch (g_scumm->_gameId) { //fixme: add all
|
|
// case GID_TENTACLE : case GID_MONKEY2 : case GID_INDY4 : shortkey=shortkey1; break;
|
|
// case GID_INDY3 : case GID_ZAK256 : case GID_MONKEY : shortkey=shortkey2; break;
|
|
// case GID_SAMNMAX : shortkey=shortkey3; break;
|
|
// default : shortkey=shortkey0; break;
|
|
//}
|
|
|
|
shortkey = shortkey0;
|
|
|
|
// Avoid redundant res changes
|
|
if ((int)w == _screenWidth && (int)h == _screenHeight)
|
|
return;
|
|
|
|
_screenWidth = w;
|
|
_screenHeight = h;
|
|
CKSUM_NUM = (_screenWidth * _screenHeight / (8 * 8));
|
|
if (_dirty_checksums)
|
|
free(_dirty_checksums);
|
|
_dirty_checksums = (uint32 *) calloc(CKSUM_NUM * 2, sizeof(uint32));
|
|
|
|
_mouseData = NULL;
|
|
unload_gfx_mode();
|
|
load_gfx_mode();
|
|
return;
|
|
}
|
|
|
|
void OSystem_GP32::add_dirty_rect(int x, int y, int w, int h) {
|
|
if (_forceFull)
|
|
return;
|
|
|
|
if (_num_dirty_rects == NUM_DIRTY_RECT)
|
|
_forceFull = true;
|
|
else {
|
|
gpRect *r = &_dirty_rect_list[_num_dirty_rects++];
|
|
|
|
// Extend the dirty region by 1 pixel for scalers
|
|
// that "smear" the screen, e.g. 2xSAI
|
|
if (_mode_flags & DF_UPDATE_EXPAND_1_PIXEL) {
|
|
x--;
|
|
y--;
|
|
w += 2;
|
|
h += 2;
|
|
}
|
|
// clip
|
|
if (x < 0) {
|
|
w += x;
|
|
x = 0;
|
|
}
|
|
if (y < 0) {
|
|
h += y;
|
|
y = 0;
|
|
}
|
|
if (w > _screenWidth - x) {
|
|
w = _screenWidth - x;
|
|
}
|
|
if (h > _screenHeight - y) {
|
|
h = _screenHeight - y;
|
|
}
|
|
|
|
r->x = x;
|
|
r->y = y;
|
|
r->w = w;
|
|
r->h = h;
|
|
}
|
|
}
|
|
|
|
void OSystem_GP32::mk_checksums(const byte *buf) {
|
|
uint32 *sums = _dirty_checksums;
|
|
uint x, y;
|
|
const uint last_x = (uint) _screenWidth / 8;
|
|
const uint last_y = (uint) _screenHeight / 8;
|
|
|
|
const uint BASE = 65521; /* largest prime smaller than 65536 */
|
|
|
|
/* the 8x8 blocks in buf are enumerated starting in the top left corner and
|
|
* reading each line at a time from left to right */
|
|
for (y = 0; y != last_y; y++, buf += _screenWidth * (8 - 1))
|
|
for (x = 0; x != last_x; x++, buf += 8) {
|
|
// Adler32 checksum algorithm (from RFC1950, used by gzip and zlib).
|
|
// This computes the Adler32 checksum of a 8x8 pixel block. Note
|
|
// that we can do the modulo operation (which is the slowest part)
|
|
// of the algorithm) at the end, instead of doing each iteration,
|
|
// since we only have 64 iterations in total - and thus s1 and
|
|
// s2 can't overflow anyway.
|
|
uint32 s1 = 1;
|
|
uint32 s2 = 0;
|
|
const byte *ptr = buf;
|
|
for (int subY = 0; subY < 8; subY++) {
|
|
for (int subX = 0; subX < 8; subX++) {
|
|
s1 += ptr[subX];
|
|
s2 += s1;
|
|
}
|
|
ptr += _screenWidth;
|
|
}
|
|
|
|
s1 %= BASE;
|
|
s2 %= BASE;
|
|
|
|
/* output the checksum for this block */
|
|
*sums++ = (s2 << 16) + s1;
|
|
}
|
|
}
|
|
|
|
void OSystem_GP32::add_dirty_rgn_auto(const byte *buf) {
|
|
assert(((uint32) buf & 3) == 0);
|
|
|
|
/* generate a table of the checksums */
|
|
mk_checksums(buf);
|
|
|
|
if (!cksum_valid) {
|
|
_forceFull = true;
|
|
cksum_valid = true;
|
|
}
|
|
|
|
/* go through the checksum list, compare it with the previous checksums,
|
|
* and add all dirty rectangles to a list. try to combine small rectangles
|
|
* into bigger ones in a simple way */
|
|
if (!_forceFull) {
|
|
int x, y, w;
|
|
uint32 *ck = _dirty_checksums;
|
|
|
|
for (y = 0; y != _screenHeight / 8; y++) {
|
|
for (x = 0; x != _screenWidth / 8; x++, ck++) {
|
|
if (ck[0] != ck[CKSUM_NUM]) {
|
|
/* found a dirty 8x8 block, now go as far to the right as possible,
|
|
* and at the same time, unmark the dirty status by setting old to new. */
|
|
w = 0;
|
|
do {
|
|
ck[w + CKSUM_NUM] = ck[w];
|
|
w++;
|
|
} while (x + w != _screenWidth / 8
|
|
&& ck[w] != ck[w + CKSUM_NUM]);
|
|
|
|
add_dirty_rect(x * 8, y * 8, w * 8, 8);
|
|
|
|
if (_forceFull)
|
|
goto get_out;
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
get_out:;
|
|
/* Copy old checksums to new */
|
|
memcpy(_dirty_checksums + CKSUM_NUM, _dirty_checksums,
|
|
CKSUM_NUM * sizeof(uint32));
|
|
}
|
|
}
|
|
|
|
// Draw a bitmap to screen.
|
|
// The screen will not be updated to reflect the new bitmap
|
|
void OSystem_GP32::copyRectToScreen(const byte *buf, int pitch, int x, int y,
|
|
int w, int h) {
|
|
if (_screen == NULL)
|
|
return;
|
|
|
|
if (pitch == _screenWidth && x == 0 && y == 0 && w == _screenWidth
|
|
&& h == _screenHeight && _mode_flags & DF_WANT_RECT_OPTIM) {
|
|
/* Special, optimized case for full screen updates.
|
|
* It tries to determine what areas were actually changed,
|
|
* and just updates those, on the actual display. */
|
|
add_dirty_rgn_auto(buf);
|
|
} else {
|
|
/* Clip the coordinates */
|
|
if (x < 0) {
|
|
w += x;
|
|
buf -= x;
|
|
x = 0;
|
|
}
|
|
if (y < 0) {
|
|
h += y;
|
|
buf -= y * pitch;
|
|
y = 0;
|
|
}
|
|
if (w > _screenWidth - x) {
|
|
w = _screenWidth - x;
|
|
}
|
|
if (h > _screenHeight - y) {
|
|
h = _screenHeight - y;
|
|
}
|
|
|
|
if (w <= 0 || h <= 0)
|
|
return;
|
|
|
|
cksum_valid = false;
|
|
add_dirty_rect(x, y, w, h);
|
|
}
|
|
|
|
/* FIXME: undraw mouse only if the draw rect intersects with the mouse rect */
|
|
if (_mouseDrawn)
|
|
undraw_mouse();
|
|
|
|
byte *dst = (byte *) _screen->pixels + y * _screenWidth + x;
|
|
do {
|
|
memcpy(dst, buf, w);
|
|
dst += _screenWidth;
|
|
buf += pitch;
|
|
} while (--h);
|
|
}
|
|
|
|
gpSurface *gpCreateRGBSurface(Uint32 flags, int width, int height, int depth,
|
|
Uint32 Rmask, Uint32 Gmask, Uint32 Bmask, Uint32 Amask) {
|
|
|
|
gpSurface *surf = (gpSurface *) malloc(sizeof(gpSurface));
|
|
surf->format = (gpPixelFormat *) malloc(sizeof(gpPixelFormat));
|
|
|
|
if ((flags & gpHWSurface) == gpHWSurface) {
|
|
error(">HW surface (w=%d, h=%d)", width, height);
|
|
} else if ((flags & gpSWSurface) == gpSWSurface) {
|
|
int size = width * height * (depth / 8);
|
|
printf(">SW surface (w=%d, h=%d, size=%d, depth=%d)", width,
|
|
height, size, depth);
|
|
surf->pixels = malloc(size);
|
|
} else {
|
|
error(">unknown surface", width, height);
|
|
return NULL;
|
|
}
|
|
surf->w = width;
|
|
surf->h = height;
|
|
surf->pitch = width * (depth / 8);
|
|
surf->format->BitsPerPixel = depth;
|
|
surf->format->BytesPerPixel = depth / 8;
|
|
return surf;
|
|
}
|
|
|
|
gpSurface *gpSetVideoMode(int width, int height, int bpp, Uint32 flags) {
|
|
return gpCreateRGBSurface(flags, width, height, bpp, 0, 0, 0, 0);
|
|
}
|
|
|
|
void gpFreeSurface(gpSurface *surface) {
|
|
// implement
|
|
}
|
|
|
|
gpSurface *gpCreateRGBSurfaceFrom(void *pixels,
|
|
int width, int height, int depth, int pitch,
|
|
Uint32 Rmask, Uint32 Gmask, Uint32 Bmask, Uint32 Amask) {
|
|
|
|
// FIXME dont reuse code
|
|
|
|
gpSurface *surf = (gpSurface *) malloc(sizeof(gpSurface));
|
|
surf->format = (gpPixelFormat *) malloc(sizeof(gpPixelFormat));
|
|
|
|
surf->w = width;
|
|
surf->h = height;
|
|
surf->pitch = pitch;
|
|
surf->pixels = pixels;
|
|
surf->format->BitsPerPixel = depth;
|
|
surf->format->BytesPerPixel = depth / 8;
|
|
return surf;
|
|
}
|
|
|
|
int gpFillRect(gpSurface *dst, gpRect *dstrect, Uint32 color) {
|
|
// FIXME: implement
|
|
return 0;
|
|
}
|
|
|
|
int mcshake = 0;
|
|
|
|
void gpUpdateRects(gpSurface *screen, int numrects, gpRect *rects) {
|
|
// FIXME dont duplicate code :)
|
|
// CHECK: shake causes crash? mcshake can get negative?
|
|
|
|
if (screen->format->BitsPerPixel == 8)
|
|
while (numrects--) {
|
|
//if (mcshake && rects->h == LCD_HEIGHT) { //fixme?
|
|
if (mcshake && rects->h == /*_screenHeight*/ 200) { //fixme?
|
|
//printf("shaking %d", mcshake);
|
|
rects->h -= mcshake;
|
|
GpRectFill(NULL, &LCDbuffer[GAME_SURFACE], 0, rects->h + scrofsy, 320, mcshake, 0); //black border
|
|
}
|
|
|
|
u8 *s =
|
|
(u8 *) ((u8 *) screen->pixels + (rects->y +
|
|
mcshake) * 320 + rects->x);
|
|
u8 *d =
|
|
(u8 *) ((u8 *) LCDbuffer[GAME_SURFACE].ptbuffer +
|
|
rects->x * 240 + scrofsy - rects->y);
|
|
u8 *s2 = s, *d2 = d;
|
|
|
|
for (int x = rects->w; x; x--) {
|
|
for (int y = rects->h; y; y--) {
|
|
*d-- = *s;
|
|
s += 320; // FIXME? screen->pitch;
|
|
}
|
|
d2 += 240;
|
|
d = d2;
|
|
s2++;
|
|
s = s2;
|
|
}
|
|
rects++;
|
|
} else if (screen->format->BitsPerPixel == 16)
|
|
while (numrects--) {
|
|
u16 *s =
|
|
(u16 *) ((u16 *) screen->pixels + rects->y * 320 +
|
|
rects->x);
|
|
u16 *d =
|
|
(u16 *) ((u16 *) LCDbuffer[GAME_SURFACE].ptbuffer +
|
|
rects->x * 240 + scrofsy - rects->y);
|
|
u16 *s2 = s, *d2 = d;
|
|
|
|
for (int x = rects->w; x; x--) {
|
|
for (int y = rects->h; y; y--) {
|
|
*d-- = *s;
|
|
s += 320; // FIXME? screen->pitch;
|
|
}
|
|
d2 += 240;
|
|
d = d2;
|
|
s2++;
|
|
s = s2;
|
|
}
|
|
rects++;
|
|
} else
|
|
error("blitting surface with wrong depth (%d)",
|
|
screen->format->BitsPerPixel);
|
|
// eh? works also when rects++ is here??
|
|
}
|
|
|
|
//#define gpBlitSurface gpUpperBlit
|
|
int gpBlitSurface(gpSurface *screen, gpRect *rects, gpSurface *dst, gpRect *dstrect) {
|
|
// FIXME? role??
|
|
//gpUpdateRects(screen, 1, rects); //ph0x! _hwscreen
|
|
return 0;
|
|
}
|
|
|
|
int gpSetColors(gpSurface *surface, gpColor *colors, int firstcolor, int ncolors) {
|
|
float rr, gg, bb;
|
|
gpColor colors2[256];
|
|
|
|
if (currentsurf == DEBUG_SURFACE)
|
|
return 1;
|
|
|
|
for (int i = firstcolor; i < firstcolor + ncolors; i++) {
|
|
rr = colors[i].r * gammatab[colors[i].r];
|
|
gg = colors[i].g * gammatab[colors[i].g];
|
|
bb = colors[i].b * gammatab[colors[i].b];
|
|
|
|
if (rr > 255)
|
|
rr = 255;
|
|
if (gg > 255)
|
|
gg = 255;
|
|
if (bb > 255)
|
|
bb = 255;
|
|
|
|
colors2[i].r = (u8) rr;
|
|
colors2[i].g = (u8) gg;
|
|
colors2[i].b = (u8) bb;
|
|
}
|
|
|
|
GpPaletteEntryChangeEx(firstcolor, ncolors, (GP_LOGPALENTRY *) colors2,
|
|
0);
|
|
return 1;
|
|
}
|
|
|
|
// Moves the screen content around by the given amount of pixels
|
|
// but only the top height pixel rows, the rest stays untouched
|
|
//void OSystem_GP32::move_screen(int dx, int dy, int height)
|
|
//{
|
|
// if ((dx == 0) && (dy == 0))
|
|
// return;
|
|
//
|
|
// if (dx == 0) {
|
|
// // vertical movement
|
|
// if (dy > 0) {
|
|
// // move down
|
|
// // copy from bottom to top
|
|
// for (int y = height - 1; y >= dy; y--)
|
|
// copyRectToScreen((byte *)_screen->pixels + _screenWidth * (y - dy), _screenWidth, 0, y, _screenWidth, 1);
|
|
// } else {
|
|
// // move up
|
|
// // copy from top to bottom
|
|
// for (int y = 0; y < height + dx; y++)
|
|
// copyRectToScreen((byte *)_screen->pixels + _screenWidth * (y - dy), _screenWidth, 0, y, _screenWidth, 1);
|
|
// }
|
|
// } else if (dy == 0) {
|
|
// // horizontal movement
|
|
// if (dx > 0) {
|
|
// // move right
|
|
// // copy from right to left
|
|
// for (int x = _screenWidth - 1; x >= dx; x--)
|
|
// copyRectToScreen((byte *)_screen->pixels + x - dx, _screenWidth, x, 0, 1, height);
|
|
// } else {
|
|
// // move left
|
|
// // copy from left to right
|
|
// for (int x = 0; x < _screenWidth; x++)
|
|
// copyRectToScreen((byte *)_screen->pixels + x - dx, _screenWidth, x, 0, 1, height);
|
|
// }
|
|
// } else {
|
|
// // free movement
|
|
// // not necessary for now
|
|
// }
|
|
//}
|
|
|
|
int16 OSystem_GP32::get_height() {
|
|
return _screenHeight;
|
|
}
|
|
|
|
int16 OSystem_GP32::get_width() {
|
|
return _screenWidth;
|
|
}
|
|
|
|
//void OSystem_GP32::warpMouse(int, int)
|
|
//{
|
|
//}
|
|
|
|
void OSystem_GP32::warpMouse(int x, int y) {
|
|
// set_mouse_pos(x, y);
|
|
}
|
|
|
|
void OSystem_GP32::load_gfx_mode() {
|
|
|
|
GpRectFill(NULL, &LCDbuffer[GAME_SURFACE], 0, 0, 320, 240, 0); //black border
|
|
|
|
_forceFull = true;
|
|
_mode_flags = DF_WANT_RECT_OPTIM | DF_UPDATE_EXPAND_1_PIXEL;
|
|
|
|
_tmpscreen = NULL;
|
|
TMP_SCREEN_WIDTH = (_screenWidth + 3);
|
|
|
|
switch (_mode) {
|
|
|
|
case GFX_NORMAL:
|
|
//???????
|
|
//normal_mode:;
|
|
_scaleFactor = 1;
|
|
_scaler_proc = Normal1x;
|
|
|
|
break;
|
|
default:
|
|
error("Unknown graphics mode");
|
|
_scaleFactor = 1;
|
|
_scaler_proc = NULL;
|
|
}
|
|
|
|
//
|
|
// Create the surface that contains the 8 bit game data
|
|
//
|
|
_screen =
|
|
gpCreateRGBSurface(gpSWSurface, _screenWidth, _screenHeight, 8, 0,
|
|
0, 0, 0);
|
|
if (_screen == NULL)
|
|
error("_screen failed");
|
|
|
|
//
|
|
// Create the surface that contains the scaled graphics in 16 bit mode
|
|
//
|
|
_hwscreen =
|
|
gpSetVideoMode(_screenWidth * _scaleFactor,
|
|
_screenHeight * _scaleFactor, 16,
|
|
_full_screen ? (gpFullScreen | gpSWSurface) : gpSWSurface);
|
|
if (_hwscreen == NULL)
|
|
error("_hwscreen failed");
|
|
|
|
//
|
|
// Create the surface used for the graphics in 16 bit before scaling, and also the overlay
|
|
//
|
|
|
|
/*
|
|
// Distinguish 555 and 565 mode
|
|
if (_hwscreen->format->Rmask == 0x7C00)
|
|
InitScalers(555);
|
|
else
|
|
InitScalers(565);
|
|
*/
|
|
//InitScalers(555); // ph0x fixme?
|
|
|
|
//ph0x fixme - tmpscreen needed?
|
|
|
|
// Need some extra bytes around when using 2xSaI
|
|
uint16 *tmp_screen =
|
|
(uint16 *) calloc(TMP_SCREEN_WIDTH * (_screenHeight + 3),
|
|
sizeof(uint16));
|
|
_tmpscreen =
|
|
gpCreateRGBSurfaceFrom(tmp_screen, TMP_SCREEN_WIDTH,
|
|
_screenHeight + 3, 16, TMP_SCREEN_WIDTH * 2,
|
|
_hwscreen->format->Rmask, _hwscreen->format->Gmask,
|
|
_hwscreen->format->Bmask, _hwscreen->format->Amask);
|
|
|
|
if (_tmpscreen == NULL)
|
|
error("_tmpscreen failed");
|
|
|
|
// keyboard cursor control, some other better place for it?
|
|
km.x_max = _screenWidth * _scaleFactor - 1;
|
|
km.y_max = _screenHeight * _scaleFactor - 1;
|
|
//km.delay_time = 25;
|
|
km.delay_time = 15;
|
|
km.last_time = 0;
|
|
|
|
}
|
|
|
|
void OSystem_GP32::unload_gfx_mode() {
|
|
if (_screen) {
|
|
gpFreeSurface(_screen);
|
|
_screen = NULL;
|
|
}
|
|
|
|
if (_hwscreen) {
|
|
gpFreeSurface(_hwscreen);
|
|
_hwscreen = NULL;
|
|
}
|
|
|
|
if (_tmpscreen) {
|
|
free((uint16 *) _tmpscreen->pixels);
|
|
gpFreeSurface(_tmpscreen);
|
|
_tmpscreen = NULL;
|
|
}
|
|
}
|
|
|
|
#include "common/util.h"
|
|
|
|
void OSystem_GP32::draw_mouse() {
|
|
if (!_overlayVisible) {
|
|
|
|
if (_mouseDrawn || !_mouseVisible)
|
|
return;
|
|
|
|
int x = _mouseCurState.x - _mouseHotspotX;
|
|
int y = _mouseCurState.y - _mouseHotspotY;
|
|
int w = _mouseCurState.w;
|
|
int h = _mouseCurState.h;
|
|
byte color;
|
|
byte *src = _mouseData; // Image representing the mouse
|
|
byte *bak = _mouseBackup; // Surface used to backup the area obscured by the mouse
|
|
byte *dst; // Surface we are drawing into
|
|
|
|
// clip the mouse rect, and addjust the src pointer accordingly
|
|
if (x < 0) {
|
|
w += x;
|
|
src -= x;
|
|
x = 0;
|
|
}
|
|
if (y < 0) {
|
|
h += y;
|
|
src -= y * _mouseCurState.w;
|
|
y = 0;
|
|
}
|
|
if (w > _screenWidth - x)
|
|
w = _screenWidth - x;
|
|
if (h > _screenHeight - y)
|
|
h = _screenHeight - y;
|
|
|
|
// Quick check to see if anything has to be drawn at all
|
|
if (w <= 0 || h <= 0)
|
|
return;
|
|
|
|
// Store the bounding box so that undraw mouse can restore the area the
|
|
// mouse currently covers to its original content.
|
|
_mouseOldState.x = x;
|
|
_mouseOldState.y = y;
|
|
_mouseOldState.w = w;
|
|
_mouseOldState.h = h;
|
|
|
|
// Draw the mouse cursor; backup the covered area in "bak"
|
|
|
|
///if (gpLockSurface(_screen) == -1)
|
|
/// error("gpLockSurface failed: %s.\n", gpGetError());
|
|
|
|
// as dirty
|
|
add_dirty_rect(x, y, w, h);
|
|
|
|
dst = (byte *) _screen->pixels + y * _screenWidth + x;
|
|
while (h > 0) {
|
|
int width = w;
|
|
while (width > 0) {
|
|
*bak++ = *dst;
|
|
color = *src++;
|
|
if (color != _mouseKeycolor) // Transparent, don't draw
|
|
*dst = color;
|
|
dst++;
|
|
width--;
|
|
}
|
|
src += _mouseCurState.w - w;
|
|
bak += MAX_MOUSE_W - w;
|
|
dst += _screenWidth - w;
|
|
h--;
|
|
}
|
|
|
|
///gpUnlockSurface(_screen);
|
|
|
|
// Finally, set the flag to indicate the mouse has been drawn
|
|
_mouseDrawn = true;
|
|
}
|
|
|
|
if (_mouseDrawn || !_mouseVisible)
|
|
return;
|
|
|
|
int x = _mouseCurState.x - _mouseHotspotX;
|
|
int y = _mouseCurState.y - _mouseHotspotY;
|
|
int w = _mouseCurState.w;
|
|
int h = _mouseCurState.h;
|
|
byte color;
|
|
//byte *src = _mouseData; // Image representing the mouse
|
|
//uint16 *src = _mouseData; // Image representing the mouse
|
|
const byte *src = _mouseData; // Image representing the mouse
|
|
//byte *bak = _mouseBackup; // Surface used to backup the area obscured by the mouse
|
|
//byte *dst; // Surface we are drawing into
|
|
|
|
//uint16 *bak = (uint16*)_mouseBackup; // Surface used to backup the area obscured by the mouse
|
|
//uint16 *dst; // Surface we are drawing into
|
|
|
|
// clip the mouse rect, and addjust the src pointer accordingly
|
|
if (x < 0) {
|
|
w += x;
|
|
src -= x;
|
|
x = 0;
|
|
}
|
|
if (y < 0) {
|
|
h += y;
|
|
src -= y * _mouseCurState.w;
|
|
y = 0;
|
|
}
|
|
// Quick check to see if anything has to be drawn at all
|
|
if (w <= 0 || h <= 0)
|
|
return;
|
|
|
|
if (w > _screenWidth - x)
|
|
w = _screenWidth - x;
|
|
if (h > _screenHeight - y)
|
|
h = _screenHeight - y;
|
|
|
|
// Store the bounding box so that undraw mouse can restore the area the
|
|
// mouse currently covers to its original content.
|
|
_mouseOldState.x = x;
|
|
_mouseOldState.y = y;
|
|
_mouseOldState.w = w;
|
|
_mouseOldState.h = h;
|
|
|
|
// Draw the mouse cursor; backup the covered area in "bak"
|
|
|
|
///if (gpLockSurface(_tmpscreen) == -1)
|
|
/// error("gpLockSurface failed: %s.\n", gpGetError());
|
|
|
|
// as dirty
|
|
add_dirty_rect(x, y, w, h);
|
|
|
|
uint16 *bak = (uint16 *) _mouseBackup; // Surface used to backup the area obscured by the mouse
|
|
uint16 *dst; // Surface we are drawing into
|
|
|
|
dst =
|
|
(uint16 *) _tmpscreen->pixels + (y + 1) * TMP_SCREEN_WIDTH + (x +
|
|
1);
|
|
while (h > 0) {
|
|
int width = w;
|
|
while (width > 0) {
|
|
*bak++ = *dst;
|
|
color = *src++;
|
|
if (color != 0xFF) // 0xFF = transparent, don't draw
|
|
*dst =
|
|
RGB_TO_16(_currentPalette[color].r,
|
|
_currentPalette[color].g,
|
|
_currentPalette[color].b);
|
|
dst++;
|
|
width--;
|
|
}
|
|
src += _mouseCurState.w - w;
|
|
bak += MAX_MOUSE_W - w;
|
|
dst += TMP_SCREEN_WIDTH - w;
|
|
h--;
|
|
}
|
|
|
|
///gpUnlockSurface(_tmpscreen);
|
|
|
|
// Finally, set the flag to indicate the mouse has been drawn
|
|
_mouseDrawn = true;
|
|
}
|
|
|
|
void OSystem_GP32::undraw_mouse() {
|
|
//return; //fixme!
|
|
if (!_overlayVisible) {
|
|
|
|
if (!_mouseDrawn)
|
|
return;
|
|
_mouseDrawn = false;
|
|
|
|
byte *dst, *bak = _mouseBackup;
|
|
const int old_mouse_x = _mouseOldState.x;
|
|
const int old_mouse_y = _mouseOldState.y;
|
|
const int old_mouse_w = _mouseOldState.w;
|
|
const int old_mouse_h = _mouseOldState.h;
|
|
int x, y;
|
|
|
|
// No need to do clipping here, since draw_mouse() did that already
|
|
|
|
dst =
|
|
(byte *) _screen->pixels + old_mouse_y * _screenWidth +
|
|
old_mouse_x;
|
|
for (y = 0; y < old_mouse_h;
|
|
++y, bak += MAX_MOUSE_W, dst += _screenWidth) {
|
|
for (x = 0; x < old_mouse_w; ++x) {
|
|
dst[x] = bak[x];
|
|
}
|
|
}
|
|
|
|
add_dirty_rect(old_mouse_x, old_mouse_y, old_mouse_w,
|
|
old_mouse_h);
|
|
}
|
|
|
|
if (!_mouseDrawn)
|
|
return;
|
|
_mouseDrawn = false;
|
|
|
|
uint16 *dst, *bak = (uint16 *) _mouseBackup;
|
|
const int old_mouse_x = _mouseOldState.x;
|
|
const int old_mouse_y = _mouseOldState.y;
|
|
const int old_mouse_w = _mouseOldState.w;
|
|
const int old_mouse_h = _mouseOldState.h;
|
|
int x, y;
|
|
|
|
// No need to do clipping here, since draw_mouse() did that already
|
|
|
|
dst =
|
|
(uint16 *) _tmpscreen->pixels + (old_mouse_y +
|
|
1) * TMP_SCREEN_WIDTH + (old_mouse_x + 1);
|
|
for (y = 0; y < old_mouse_h;
|
|
++y, bak += MAX_MOUSE_W, dst += TMP_SCREEN_WIDTH) {
|
|
for (x = 0; x < old_mouse_w; ++x) {
|
|
dst[x] = bak[x];
|
|
}
|
|
}
|
|
|
|
add_dirty_rect(old_mouse_x, old_mouse_y, old_mouse_w, old_mouse_h);
|
|
}
|
|
|
|
char *gpGetError(void) {
|
|
// FIXME: implement
|
|
return NULL;
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// GP32 Screen Update Stuff - Mostly 'borrowed' from GP but using gpSDK
|
|
//
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
//// Update the dirty areas of the screen
|
|
void OSystem_GP32::updateScreen() {
|
|
//Common::StackLock lock(_graphicsMutex); // Lock the mutex until this function ends
|
|
internUpdateScreen();
|
|
}
|
|
|
|
// assert(_hwscreen != NULL);
|
|
//
|
|
// // If the shake position changed, fill the dirty area with blackness
|
|
// if (_currentShakePos != _newShakePos) {
|
|
// gpRect blackrect = {0, 0, _screenWidth*_scaleFactor, _newShakePos*_scaleFactor};
|
|
//
|
|
// if (_adjustAspectRatio)
|
|
// blackrect.h = real2Aspect(blackrect.h - 1) + 1;
|
|
//
|
|
// gpFillRect(_hwscreen, &blackrect, 0);
|
|
//
|
|
// _currentShakePos = _newShakePos;
|
|
//
|
|
// _forceFull = true;
|
|
// }
|
|
//
|
|
// // Make sure the mouse is drawn, if it should be drawn.
|
|
// draw_mouse();
|
|
//
|
|
// // Check whether the palette was changed in the meantime and update the
|
|
// // screen surface accordingly.
|
|
// if (_paletteDirtyEnd != 0) {
|
|
// gpSetColors(_screen, _currentPalette + _paletteDirtyStart,
|
|
// _paletteDirtyStart,
|
|
// _paletteDirtyEnd - _paletteDirtyStart);
|
|
//
|
|
// _paletteDirtyEnd = 0;
|
|
//
|
|
// _forceFull = true;
|
|
// }
|
|
//
|
|
// // Force a full redraw if requested
|
|
// if (_forceFull) {
|
|
// _num_dirty_rects = 1;
|
|
//
|
|
// _dirty_rect_list[0].x = 0;
|
|
// _dirty_rect_list[0].y = 0;
|
|
// _dirty_rect_list[0].w = _screenWidth;
|
|
// _dirty_rect_list[0].h = _screenHeight;
|
|
// }
|
|
//
|
|
// // Only draw anything if necessary
|
|
// if (_num_dirty_rects > 0) {
|
|
//
|
|
// gpRect *r;
|
|
// uint32 srcPitch, dstPitch;
|
|
// gpRect *last_rect = _dirty_rect_list + _num_dirty_rects;
|
|
//
|
|
// // Convert appropriate parts of the 8bpp image into 16bpp
|
|
// if (!_overlayVisible) {
|
|
// gpRect dst;
|
|
// for(r = _dirty_rect_list; r != last_rect; ++r) {
|
|
// dst = *r;
|
|
// dst.x++; // FIXME? Shift rect by one since 2xSai needs to acces the data around
|
|
// dst.y++; // FIXME? any pixel to scale it, and we want to avoid mem access crashes.
|
|
//
|
|
// if (gpBlitSurface(_screen, r, _hwscreen, &dst) != 0) //ph0x! _tmpscreen
|
|
// error("gpBlitSurface failed: %s", gpGetError());
|
|
// }
|
|
// }
|
|
//
|
|
//// ph0x! (no scaling) cannot skip intro if commented?
|
|
//
|
|
// srcPitch = _tmpscreen->pitch;
|
|
// dstPitch = _hwscreen->pitch;
|
|
// for(r = _dirty_rect_list; r != last_rect; ++r) {
|
|
// register int dst_y = r->y + _currentShakePos;
|
|
// register int dst_h = 0;
|
|
// if (dst_y < _screenHeight) {
|
|
// dst_h = r->h;
|
|
// if (dst_h > _screenHeight - dst_y)
|
|
// dst_h = _screenHeight - dst_y;
|
|
//
|
|
// dst_y *= _scaleFactor;
|
|
//
|
|
// if (_overlayVisible) //ph0x fixme?
|
|
// _scaler_proc((byte*)_tmpscreen->pixels + (r->x*2+2) + (r->y+1)*srcPitch, srcPitch,
|
|
// (byte*)_hwscreen->pixels + r->x*2*_scaleFactor + dst_y*dstPitch, dstPitch, r->w, dst_h);
|
|
// }
|
|
// r->x *= _scaleFactor;
|
|
// r->y = dst_y;
|
|
// r->w *= _scaleFactor;
|
|
// r->h = dst_h * _scaleFactor;
|
|
// }
|
|
//
|
|
// // Readjust the dirty rect list in case we are doing a full update.
|
|
// // This is necessary if shaking is active.
|
|
// if (_forceFull) {
|
|
// _dirty_rect_list[0].y = 0;
|
|
// _dirty_rect_list[0].h = _screenHeight * _scaleFactor;
|
|
// }
|
|
//
|
|
// // Finally, blit all our changes to the screen
|
|
//
|
|
// // FIXME (dont use condition)
|
|
// if (_overlayVisible)
|
|
// gpUpdateRects(_hwscreen, _num_dirty_rects, _dirty_rect_list); //ph0x! _hwscreen
|
|
// else
|
|
// gpUpdateRects(_screen, _num_dirty_rects, _dirty_rect_list);
|
|
// }
|
|
//
|
|
// _num_dirty_rects = 0;
|
|
// _forceFull = false;
|
|
//}
|
|
|
|
// Either show or hide the mouse cursor
|
|
bool OSystem_GP32::showMouse(bool visible) {
|
|
if (_mouseVisible == visible)
|
|
return visible;
|
|
|
|
bool last = _mouseVisible;
|
|
_mouseVisible = visible;
|
|
|
|
if (visible)
|
|
draw_mouse();
|
|
else
|
|
undraw_mouse();
|
|
|
|
return last;
|
|
}
|
|
|
|
// Set the position of the mouse cursor
|
|
void OSystem_GP32::set_mouse_pos(int x, int y) {
|
|
if (x != _mouseCurState.x || y != _mouseCurState.y) {
|
|
_mouseCurState.x = x;
|
|
_mouseCurState.y = y;
|
|
|
|
mx = x; //ph0x fixme
|
|
my = y; //ph0x fixme
|
|
undraw_mouse();
|
|
}
|
|
}
|
|
|
|
// Set the bitmap that's used when drawing the cursor.
|
|
void OSystem_GP32::setMouseCursor(const byte *buf, uint w, uint h,
|
|
int hotspot_x, int hotspot_y, byte keycolor, int cursorTargetScale) {
|
|
|
|
// assert(w <= MAX_MOUSE_W);
|
|
// assert(h <= MAX_MOUSE_H);
|
|
|
|
_mouseCurState.w = w;
|
|
_mouseCurState.h = h;
|
|
|
|
_mouseHotspotX = hotspot_x;
|
|
_mouseHotspotY = hotspot_y;
|
|
|
|
_mouseKeycolor = keycolor;
|
|
|
|
//??????????
|
|
_mouseData = (byte *) buf;
|
|
|
|
undraw_mouse();
|
|
|
|
if (_mouseData)
|
|
free(_mouseData);
|
|
|
|
_mouseData = (byte *) malloc(w * h);
|
|
|
|
memcpy(_mouseData, buf, w * h);
|
|
}
|
|
|
|
// Shaking is used in SCUMM. Set current shake position.
|
|
void OSystem_GP32::setShakePos(int shake_pos) {
|
|
_newShakePos = shake_pos;
|
|
mcshake = shake_pos;
|
|
}
|
|
|
|
// Get the number of milliseconds since the program was started.
|
|
uint32 OSystem_GP32::getMillis() {
|
|
return GpTickCountGet();
|
|
}
|
|
|
|
// Delay for a specified amount of milliseconds
|
|
void OSystem_GP32::delayMillis(uint msecs) {
|
|
int n = GpTickCountGet();
|
|
while ((GpTickCountGet() - n) < msecs);
|
|
}
|
|
|
|
// Get the next event.
|
|
// Returns true if an event was retrieved.
|
|
|
|
const signed char abc[] = "0123456789abcdefghijklmnopqrstuvwxyz";
|
|
signed int abcindex = -1;
|
|
|
|
void switchsurf(int surf);
|
|
void buildgammatab(int val);
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// GP32 Event Handlers.
|
|
//
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
bool OSystem_GP32::pollEvent(Event & event) {
|
|
|
|
#define EVENT_COUNT 2 // >=1
|
|
//#define MOUSE_MIPS 2 // bg updates wrong if >1 ??
|
|
#define MOUSE_MIPS 1 // bg updates wrong if >1 ??
|
|
|
|
static int lastkey, eventcount = EVENT_COUNT, lastevent = 0;
|
|
static int simulate;
|
|
static bool backspace = true;
|
|
static uint32 t;
|
|
int key;
|
|
|
|
key = gpTrapKey();
|
|
|
|
if (simulate)
|
|
simulate--;
|
|
switch (simulate) {
|
|
case 5:
|
|
lastevent = event.type = EVENT_KEYDOWN;
|
|
event.kbd.keycode = event.kbd.ascii = 8;
|
|
return true;
|
|
break;
|
|
case 3:
|
|
lastevent = event.type = EVENT_KEYDOWN;
|
|
event.kbd.keycode = event.kbd.ascii = abc[abcindex];
|
|
return true;
|
|
break;
|
|
case 4:
|
|
case 2:
|
|
lastevent = event.type = EVENT_KEYUP;
|
|
//event.kbd.keycode = event.kbd.ascii =
|
|
return true;
|
|
break;
|
|
case 1:
|
|
lastkey = key = 0;
|
|
lastevent = 0;
|
|
event.type = (EventType) 0;
|
|
break;
|
|
}
|
|
|
|
if (lastevent == EVENT_KEYDOWN) {
|
|
lastevent = event.type = EVENT_KEYUP;
|
|
//event.kbd.keycode = event.kbd.ascii;
|
|
return true;
|
|
}
|
|
|
|
if (key == GPC_VK_NONE) {
|
|
lastevent = lastkey = 0;
|
|
return false;
|
|
}
|
|
|
|
if (key == lastkey) {
|
|
eventcount--;
|
|
if (eventcount)
|
|
return false;
|
|
}
|
|
|
|
eventcount = EVENT_COUNT;
|
|
event.type = EVENT_KEYDOWN;
|
|
|
|
if (key & GPC_VK_FL) { // L
|
|
if (_overlayVisible)
|
|
return false;
|
|
|
|
if (key & GPC_VK_UP) {
|
|
if (key == lastkey)
|
|
return false;
|
|
|
|
if (gindex < ARRAYSIZE(scrGamma) - 1)
|
|
gindex++;
|
|
buildgammatab(gindex);
|
|
_paletteDirtyStart = 0;
|
|
_paletteDirtyEnd = 255; //fixme?
|
|
lastevent = event.type;
|
|
lastkey = key;
|
|
return true;
|
|
} else
|
|
if (key & GPC_VK_DOWN) {
|
|
if (key == lastkey)
|
|
return false;
|
|
|
|
if (gindex > 0)
|
|
gindex--;
|
|
buildgammatab(gindex);
|
|
_paletteDirtyStart = 0;
|
|
_paletteDirtyEnd = 255; //fixme?
|
|
lastevent = event.type;
|
|
lastkey = key;
|
|
return true;
|
|
}
|
|
|
|
if (key == lastkey)
|
|
return false;
|
|
if (skindex > 0)
|
|
skindex--;
|
|
event.kbd.keycode = event.kbd.ascii = shortkey[skindex];
|
|
lastevent = event.type;
|
|
lastkey = key;
|
|
return true;
|
|
}
|
|
|
|
lastkey = key;
|
|
|
|
if (key & GPC_VK_FR) { // R
|
|
if (key & GPC_VK_UP) {
|
|
if (getMillis() < t)
|
|
return false;
|
|
//do key=GpKeyGet(); while (key & GPC_VK_UP);
|
|
//fixme -2/-1
|
|
t = getMillis() + 200;
|
|
if (abcindex == -1)
|
|
abcindex = 0;
|
|
else {
|
|
if (abcindex < sizeof(abc) - 2)
|
|
abcindex++;
|
|
else
|
|
abcindex = 0;
|
|
}
|
|
if (backspace)
|
|
simulate = 6;
|
|
else {
|
|
backspace = true;
|
|
simulate = 4;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
if (key & GPC_VK_DOWN) {
|
|
if (getMillis() < t)
|
|
return false;
|
|
//do key=GpKeyGet(); while (key & GPC_VK_DOWN);
|
|
//fixme -2/-1
|
|
t = getMillis() + 200;
|
|
if (abcindex == -1)
|
|
abcindex = abcindex = sizeof(abc) - 2;
|
|
else {
|
|
if (abcindex > 0)
|
|
abcindex--;
|
|
else
|
|
abcindex = sizeof(abc) - 2;
|
|
}
|
|
if (backspace)
|
|
simulate = 6;
|
|
else {
|
|
backspace = true;
|
|
simulate = 4;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
if (key & GPC_VK_LEFT) {
|
|
abcindex = -1;
|
|
event.kbd.keycode = event.kbd.ascii = 8;
|
|
lastevent = event.type;
|
|
do
|
|
key = gpTrapKey();
|
|
while (key & GPC_VK_LEFT);
|
|
return true;
|
|
} else if (key & GPC_VK_RIGHT) {
|
|
abcindex = -1;
|
|
backspace = false;
|
|
return false;
|
|
}
|
|
if (!_overlayVisible) {
|
|
if (lastevent == EVENT_KEYUP)
|
|
return false;
|
|
if (shortkey[skindex + 1])
|
|
skindex++;
|
|
event.kbd.keycode = event.kbd.ascii =
|
|
shortkey[skindex];
|
|
lastevent = event.type;
|
|
return true;
|
|
}
|
|
} else if (key & GPC_VK_START) { // START = menu/enter
|
|
if (_overlayVisible)
|
|
event.kbd.keycode = event.kbd.ascii = 13;
|
|
else {
|
|
event.kbd.keycode = event.kbd.ascii = 319;
|
|
//buildgammatab(ARRAYSIZE(scrGamma)-1); // moved to colortoRBG
|
|
}
|
|
lastevent = event.type;
|
|
return true;
|
|
}
|
|
|
|
if (key & GPC_VK_SELECT) { // SELECT == escape/skip
|
|
if (_overlayVisible) {
|
|
do
|
|
key = gpTrapKey();
|
|
while (key != GPC_VK_NONE); // prevent 2xESC
|
|
buildgammatab(gindex);
|
|
_paletteDirtyStart = 0;
|
|
_paletteDirtyEnd = 255; //fixme?
|
|
}
|
|
event.kbd.keycode = event.kbd.ascii = 27;
|
|
lastevent = event.type;
|
|
return true;
|
|
}
|
|
|
|
if (key & GPC_VK_FA) {
|
|
if (lastevent == EVENT_LBUTTONUP)
|
|
return false;
|
|
|
|
if (lastevent == EVENT_LBUTTONDOWN) {
|
|
lastevent = EVENT_LBUTTONUP;
|
|
event.type = EVENT_LBUTTONUP;
|
|
} else {
|
|
lastevent = EVENT_LBUTTONDOWN;
|
|
event.type = EVENT_LBUTTONDOWN;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
if (key & GPC_VK_FB) {
|
|
if (lastevent == EVENT_RBUTTONUP)
|
|
return false;
|
|
|
|
if (lastevent == EVENT_RBUTTONDOWN) {
|
|
lastevent = EVENT_RBUTTONUP;
|
|
event.type = EVENT_RBUTTONUP;
|
|
} else {
|
|
lastevent = EVENT_RBUTTONDOWN;
|
|
event.type = EVENT_RBUTTONDOWN;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
if (key & GPC_VK_LEFT) {
|
|
mx -= MOUSE_MIPS;
|
|
if (mx < 1)
|
|
mx = 1; // wrong if 0?
|
|
}
|
|
|
|
if (key & GPC_VK_RIGHT) {
|
|
mx += MOUSE_MIPS;
|
|
if (mx > 319)
|
|
mx = 319;
|
|
}
|
|
|
|
if (key & GPC_VK_UP) {
|
|
my -= MOUSE_MIPS;
|
|
if (my < 1)
|
|
my = 1; // wrong if 0?
|
|
}
|
|
|
|
if (key & GPC_VK_DOWN) {
|
|
my += MOUSE_MIPS;
|
|
if (my > _screenHeight - 1)
|
|
my = _screenHeight - 1;
|
|
}
|
|
|
|
event.type = EVENT_MOUSEMOVE;
|
|
km.x = event.mouse.x = mx;
|
|
km.y = event.mouse.y = my;
|
|
event.mouse.x /= _scaleFactor;
|
|
event.mouse.y /= _scaleFactor;
|
|
set_mouse_pos(event.mouse.x, event.mouse.y);
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// GP32 Graphics Stuff -
|
|
//
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
int16 OSystem_GP32::RBGToColor(uint8 r, uint8 g, uint8 b) {
|
|
float rr, gg, bb;
|
|
|
|
rr = r * gammatab2[r];
|
|
gg = g * gammatab2[g];
|
|
bb = b * gammatab2[b];
|
|
|
|
if (rr > 255)
|
|
rr = 255;
|
|
if (gg > 255)
|
|
gg = 255;
|
|
if (bb > 255)
|
|
bb = 255;
|
|
|
|
r = (u8) rr;
|
|
g = (u8) gg;
|
|
b = (u8) bb;
|
|
|
|
//return ((((r>>3)&0x1F) << 11) | (((g>>2)&0x3F) << 5) | ((b>>3)&0x1F)); //ph0x
|
|
return (((((r) >> 3) & 0x1F) << 11) | ((((g) >> 3) & 0x1F) << 6) |
|
|
(((b) >> 3) & 0x1F) << 1);
|
|
}
|
|
|
|
void OSystem_GP32::colorToRBG(int16 color, uint8 &r, uint8 &g, uint8 &b) {
|
|
float rr, gg, bb;
|
|
r = ((((color) >> 11) & 0x1F) << 3); //(((color>>11)&0x1F) << 3);
|
|
g = ((((color) >> 6) & 0x1F) << 3); //(((color>>5)&0x3F) << 2);
|
|
b = ((((color) >> 1) & 0x1F) << 3); //((color&0x1F) << 3);
|
|
|
|
rr = r * gammatab2[r];
|
|
gg = g * gammatab2[g];
|
|
bb = b * gammatab2[b];
|
|
|
|
if (rr > 255)
|
|
rr = 255;
|
|
if (gg > 255)
|
|
gg = 255;
|
|
if (bb > 255)
|
|
bb = 255;
|
|
|
|
r = (u8) rr;
|
|
g = (u8) gg;
|
|
b = (u8) bb;
|
|
}
|
|
|
|
void switchsurf(int surf) {
|
|
GPLCDINFO lcd;
|
|
GpLcdInfoGet(&lcd);
|
|
|
|
if (surf == DEBUG_SURFACE) {
|
|
if (lcd.lcd_global.U8_lcd.bpp == 16)
|
|
GpGraphicModeSet(8, NULL);
|
|
|
|
currentsurf = DEBUG_SURFACE;
|
|
GpSurfaceFlip(&LCDbuffer[(int)currentsurf]);
|
|
|
|
//GpSetPaletteEntry ( 0, 0,0,0 );
|
|
//GpSetPaletteEntry ( 1, 0,0,0 );
|
|
//GpSetPaletteEntry ( 2, 255,255,255 );
|
|
|
|
} else if (surf == GAME_SURFACE) {
|
|
//if (lcd.lcd_global.U8_lcd.bpp == 8) GpGraphicModeSet(16, NULL);
|
|
|
|
currentsurf = GAME_SURFACE;
|
|
GpSurfaceFlip(&LCDbuffer[(int)currentsurf]);
|
|
//GpSetPaletteEntry ( 2, 0,0,0 );
|
|
//GpSetPaletteEntry ( 1, 0,107,84 );
|
|
//GpSetPaletteEntry ( 0, 255,255,255 );
|
|
} else
|
|
error("Switching to false stuface");
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// GP32 Sound Stuff -
|
|
//
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
void OSystem_GP32::clearSoundCallback() {
|
|
// _sound_proc = NULL;
|
|
// _sound_proc_param = NULL;
|
|
}
|
|
|
|
typedef void SoundProc(void *param, byte *buf, int len);
|
|
|
|
typedef struct GPSOUNDBUF {
|
|
PCM_SR freq; /* Taken from gpmm.h */
|
|
PCM_BIT format; /* Taken from gpmm.h */
|
|
unsigned int samples; /* Buffer length (in samples) */
|
|
void *userdata; /* Userdata which gets passed to the callback function */
|
|
SoundProc *callback;
|
|
unsigned int pollfreq; /* Frequency of the timer interrupt which polls the playing position
|
|
* recommended value: 2*(playingfreq in Hz/GPSOUNDBUF.samples) */
|
|
unsigned int samplesize; /* Size of one sample (8bit mono->1, 16bit stereo->4) - don't touch this */
|
|
} GPSOUNDBUF;
|
|
|
|
GPSOUNDBUF gpsndbuf; // for scumm
|
|
|
|
/* Global variables */
|
|
unsigned int frame = 0;
|
|
unsigned int *soundPos = 0;
|
|
volatile int idx_buf;
|
|
unsigned int shiftVal = 0;
|
|
void *buffer;
|
|
GPSOUNDBUF soundBuf;
|
|
|
|
/* This routine gets called by the timer interrupt and
|
|
* polls the current playing position within the buffer.
|
|
*/
|
|
|
|
//void *blah; // holds "this" for mixer.cpp
|
|
|
|
void soundtimer(void) {
|
|
unsigned int t =
|
|
(((unsigned int)(*soundPos) - (unsigned int)buffer) >> shiftVal) >=
|
|
soundBuf.samples ? 1 : 0;
|
|
if (t != frame) {
|
|
unsigned int offs =
|
|
((frame == 1) ? (soundBuf.samples << shiftVal) : 0);
|
|
soundBuf.callback(soundBuf.userdata /*blah */ , (u8 *) ((unsigned int)buffer + offs), soundBuf.samples << shiftVal); //FIXME (*callback)(param) ?
|
|
frame = t;
|
|
}
|
|
}
|
|
|
|
int GpSoundBufStart(GPSOUNDBUF *sb) {
|
|
frame = 0;
|
|
|
|
/* Copy the structure */
|
|
memcpy(&soundBuf, sb, sizeof(GPSOUNDBUF));
|
|
|
|
/* Calculate size of a single sample in bytes
|
|
* and a corresponding shift value
|
|
*/
|
|
shiftVal = 0;
|
|
switch (soundBuf.freq) {
|
|
case PCM_S11:
|
|
break;
|
|
case PCM_S22:
|
|
break;
|
|
case PCM_S44:
|
|
shiftVal++;
|
|
break;
|
|
case PCM_M11:
|
|
break;
|
|
case PCM_M22:
|
|
break;
|
|
case PCM_M44:
|
|
shiftVal++;
|
|
break;
|
|
}
|
|
if (soundBuf.format == PCM_16BIT)
|
|
shiftVal++;
|
|
soundBuf.samplesize = 1 << shiftVal;
|
|
|
|
/* Allocate memory for the playing buffer */
|
|
buffer = malloc(soundBuf.samplesize * soundBuf.samples * 2);
|
|
memset(buffer, 0, soundBuf.samplesize * soundBuf.samples * 2);
|
|
|
|
/* Set timer interrupt #0 */
|
|
if (GpTimerOptSet(0, soundBuf.pollfreq, 0,
|
|
soundtimer) == GPOS_ERR_ALREADY_USED)
|
|
error("timer slot used");
|
|
GpTimerSet(0);
|
|
/* Start playing */
|
|
GpPcmPlay((unsigned short *)buffer,
|
|
soundBuf.samples * soundBuf.samplesize * 2, 1);
|
|
GpPcmLock((unsigned short *)buffer, (int *)&idx_buf,
|
|
(unsigned int *)&soundPos);
|
|
|
|
return 0;
|
|
}
|
|
|
|
void GpSoundBufStop(void) {
|
|
GpPcmStop();
|
|
GpPcmRemove((unsigned short *)buffer);
|
|
GpTimerKill(0);
|
|
free(buffer);
|
|
}
|
|
|
|
int OSystem_GP32::getOutputSampleRate() const {
|
|
return SAMPLES_PER_SEC;
|
|
}
|
|
|
|
// Set the function to be invoked whenever samples need to be generated
|
|
// Buffer Length and Poll Frequency changed. DJWillis
|
|
bool OSystem_GP32::setSoundCallback(SoundProc proc, void *param) {
|
|
gpsndbuf.freq = PCM_S22; // Taken from gpmm.h
|
|
gpsndbuf.format = PCM_16BIT; // Taken from gpmm.h
|
|
gpsndbuf.samples = 2048; //128; //fixme? // Buffer length (in samples)
|
|
//FIXME? crashes if not commented?!
|
|
//gpsndbuf.userdata=g_scumm; //param; //fixme? // Userdata which gets passed to the callback function
|
|
gpsndbuf.callback = proc; //mycallback; // Callback function (just like in SDL)
|
|
//2*((float)22025/(float)s.samples);
|
|
gpsndbuf.pollfreq = 8 * (SAMPLES_PER_SEC / gpsndbuf.samples); //fixme
|
|
// Frequency of the timer interrupt which polls the playing position
|
|
// recommended value: 2*(playingfreq in Hz/GPSOUNDBUF.samples)
|
|
//s.samplesize; // Size of one sample (8bit mono->1, 16bit stereo->4) - don't touch this
|
|
|
|
GpPcmInit(PCM_S22, PCM_16BIT);
|
|
GpSoundBufStart(&gpsndbuf);
|
|
return true;
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// GP32 Graphics Stuff
|
|
//
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
void OSystem_GP32::get_screen_image(byte *buf) {
|
|
/* make sure the mouse is gone */
|
|
undraw_mouse();
|
|
|
|
///if (gpLockSurface(_screen) == -1)
|
|
/// error("gpLockSurface failed: %s.\n", gpGetError());
|
|
|
|
memcpy(buf, _screen->pixels, _screenWidth * _screenHeight);
|
|
|
|
///gpUnlockSurface(_screen);
|
|
}
|
|
|
|
void OSystem_GP32::hotswap_gfx_mode() {
|
|
/* We allocate a screen sized bitmap which contains a "backup"
|
|
* of the screen data during the change. Then we draw that to
|
|
* the new screen right after it's setup.
|
|
*/
|
|
|
|
byte *bak_mem = (byte *) malloc(_screenWidth * _screenHeight);
|
|
|
|
get_screen_image(bak_mem);
|
|
|
|
unload_gfx_mode();
|
|
load_gfx_mode();
|
|
|
|
// reset palette
|
|
gpSetColors(_screen, _currentPalette, 0, 256);
|
|
|
|
// blit image
|
|
copyRectToScreen(bak_mem, _screenWidth, 0, 0, _screenWidth,
|
|
_screenHeight);
|
|
free(bak_mem);
|
|
|
|
updateScreen();
|
|
}
|
|
|
|
// Get or set a property
|
|
//uint32 OSystem_GP32::property(int param, Property *value)
|
|
//{
|
|
// switch(param) {
|
|
//
|
|
// case PROP_GET_FULLSCREEN:
|
|
// return _full_screen;
|
|
//}
|
|
|
|
void OSystem_GP32::setWindowCaption(const char *caption) {
|
|
//gGameName = caption; // Would like to return game here like DC port. - DJWillis
|
|
}
|
|
|
|
// CDROM Code - All returns false as the GP32 has no CDROM ;-)
|
|
|
|
bool OSystem_GP32::openCD(int drive) {
|
|
return false;
|
|
}
|
|
|
|
bool OSystem_GP32::pollCD() {
|
|
return false;
|
|
}
|
|
|
|
void OSystem_GP32::playCD(int track, int num_loops, int start_frame, int duration) {
|
|
}
|
|
|
|
void OSystem_GP32::stopCD() {
|
|
}
|
|
|
|
void OSystem_GP32::updateCD() {
|
|
}
|
|
|
|
// End CDROM Code.
|
|
|
|
// Add a new callback timer
|
|
|
|
// ph0x FIXME: make members
|
|
int _timerinterval;
|
|
int (*_timercallback)(int);
|
|
|
|
void voidcallback() {
|
|
//printf("timer running");
|
|
_timercallback(_timerinterval); //FIXME ?? (*_timercallback)(_timerinterval);
|
|
}
|
|
|
|
void OSystem_GP32::setTimerCallback(TimerProc callback, int timer) {
|
|
int timerno = 1; //0 used by sound proc
|
|
|
|
if (!callback) {
|
|
GpTimerKill(timerno);
|
|
return;
|
|
}
|
|
|
|
if (GpTimerOptSet(timerno, timer, 0,
|
|
voidcallback) == GPOS_ERR_ALREADY_USED)
|
|
error("timer slot used");
|
|
|
|
_timerinterval = timer;
|
|
_timercallback = callback;
|
|
GpTimerSet(timerno);
|
|
}
|
|
|
|
// Mutex handling - DJWillis Hack
|
|
OSystem::MutexRef OSystem_GP32::createMutex(void) {
|
|
return NULL;
|
|
}
|
|
|
|
void OSystem_GP32::lockMutex(MutexRef) {
|
|
}
|
|
|
|
void OSystem_GP32::unlockMutex(MutexRef) {
|
|
}
|
|
|
|
void OSystem_GP32::deleteMutex(MutexRef) {
|
|
}
|
|
|
|
// Quit
|
|
void OSystem_GP32::quit() {
|
|
printf("Quitting...");
|
|
exit(0);
|
|
}
|
|
|
|
// Overlay
|
|
void OSystem_GP32::showOverlay() {
|
|
// hide the mouse
|
|
undraw_mouse();
|
|
|
|
u8 *s = (u8 *) _screen->pixels;
|
|
u16 *d = (u16 *) _tmpscreen->pixels;
|
|
u8 c;
|
|
// convert to 16 bit
|
|
for (int y = 0; y < _screenHeight; y++) {
|
|
for (int x = 0; x < 320; x++) {
|
|
c = *s;
|
|
*d++ =
|
|
(u16) gpRGB16(_currentPalette[c].r,
|
|
_currentPalette[c].g, _currentPalette[c].b);
|
|
s++;
|
|
}
|
|
d += 3; // tmpscreen width is screen+3
|
|
}
|
|
GpGraphicModeSet(16, NULL); //ph0x
|
|
// Test code.
|
|
//???????????
|
|
//GpRectFill(NULL,&LCDbuffer[GAME_SURFACE], 0, 0, 320, 240, 0); //black border
|
|
_overlayVisible = true;
|
|
clearOverlay();
|
|
}
|
|
|
|
void OSystem_GP32::hideOverlay() {
|
|
// hide the mouse
|
|
undraw_mouse();
|
|
|
|
GpGraphicModeSet(8, NULL); //ph0x
|
|
GpRectFill(NULL, &LCDbuffer[GAME_SURFACE], 0, 0, 320, 240, 0); //black border
|
|
|
|
_overlayVisible = false;
|
|
_forceFull = true;
|
|
}
|
|
|
|
void OSystem_GP32::clearOverlay() {
|
|
if (!_overlayVisible)
|
|
return;
|
|
|
|
// hide the mouse
|
|
undraw_mouse();
|
|
|
|
// Clear the overlay by making the game screen "look through" everywhere.
|
|
gpRect src, dst;
|
|
src.x = src.y = 0;
|
|
dst.x = dst.y = 1;
|
|
src.w = dst.w = _screenWidth;
|
|
src.h = dst.h = _screenHeight;
|
|
if (gpBlitSurface(_screen, &src, _tmpscreen, &dst) != 0) //FIXME
|
|
error("gpBlitSurface failed: %s", gpGetError());
|
|
_forceFull = true;
|
|
}
|
|
|
|
void OSystem_GP32::grabOverlay(int16 *buf, int pitch) {
|
|
if (!_overlayVisible)
|
|
return;
|
|
|
|
if (_tmpscreen == NULL)
|
|
return;
|
|
|
|
// hide the mouse
|
|
undraw_mouse();
|
|
|
|
///if (gpLockSurface(_tmpscreen) == -1)
|
|
/// error("gpLockSurface failed: %s.\n", gpGetError());
|
|
|
|
int16 *src = (int16 *) _tmpscreen->pixels + TMP_SCREEN_WIDTH + 1;
|
|
int h = _screenHeight;
|
|
do {
|
|
memcpy(buf, src, _screenWidth * 2);
|
|
src += TMP_SCREEN_WIDTH;
|
|
buf += pitch;
|
|
} while (--h);
|
|
|
|
///gpUnlockSurface(_tmpscreen);
|
|
}
|
|
|
|
void OSystem_GP32::copyRectToOverlay(const int16 * buf, int pitch, int x,
|
|
int y, int w, int h) {
|
|
if (!_overlayVisible)
|
|
return;
|
|
|
|
if (_tmpscreen == NULL)
|
|
return;
|
|
|
|
// Clip the coordinates
|
|
if (x < 0) {
|
|
w += x;
|
|
buf -= x;
|
|
x = 0;
|
|
}
|
|
if (y < 0) {
|
|
h += y;
|
|
buf -= y * pitch;
|
|
y = 0;
|
|
}
|
|
if (w > _screenWidth - x) {
|
|
w = _screenWidth - x;
|
|
}
|
|
if (h > _screenHeight - y) {
|
|
h = _screenHeight - y;
|
|
}
|
|
if (w <= 0 || h <= 0)
|
|
return;
|
|
|
|
// Mark the modified region as dirty
|
|
cksum_valid = false;
|
|
add_dirty_rect(x, y, w, h);
|
|
|
|
/* FIXME: undraw mouse only if the draw rect intersects with the mouse rect */
|
|
undraw_mouse();
|
|
|
|
///if (gpLockSurface(_tmpscreen) == -1)
|
|
/// error("gpLockSurface failed: %s.\n", gpGetError());
|
|
|
|
int16 *dst =
|
|
(int16 *) _tmpscreen->pixels + (y + 1) * TMP_SCREEN_WIDTH + (x +
|
|
1);
|
|
do {
|
|
memcpy(dst, buf, w * 2);
|
|
dst += TMP_SCREEN_WIDTH;
|
|
buf += pitch;
|
|
} while (--h);
|
|
|
|
///gpUnlockSurface(_tmpscreen);
|
|
}
|
|
|
|
void OSystem_GP32::internUpdateScreen() {
|
|
assert(_hwscreen != NULL);
|
|
|
|
// If the shake position changed, fill the dirty area with blackness
|
|
|
|
if (_currentShakePos != _newShakePos) {
|
|
|
|
gpRect blackrect =
|
|
{ 0, 0, _screenWidth * _scaleFactor,
|
|
_newShakePos * _scaleFactor };
|
|
|
|
//if (_adjustAspectRatio)
|
|
// blackrect.h = real2Aspect(blackrect.h - 1) + 1;
|
|
|
|
gpFillRect(_hwscreen, &blackrect, 0);
|
|
|
|
_currentShakePos = _newShakePos;
|
|
|
|
_forceFull = true;
|
|
}
|
|
// Make sure the mouse is drawn, if it should be drawn.
|
|
draw_mouse();
|
|
|
|
// Check whether the palette was changed in the meantime and update the
|
|
// screen surface accordingly.
|
|
if (_paletteDirtyEnd != 0) {
|
|
|
|
gpSetColors(_screen, _currentPalette + _paletteDirtyStart,
|
|
_paletteDirtyStart, _paletteDirtyEnd - _paletteDirtyStart);
|
|
|
|
_paletteDirtyEnd = 0;
|
|
|
|
_forceFull = true;
|
|
}
|
|
//#ifdef USE_OSD
|
|
// // OSD visible (i.e. non-transparent)?
|
|
// if (_osdAlpha != gpALPHA_TRANSPARENT) {
|
|
// // Updated alpha value
|
|
// const int diff = gpGetTicks() - _osdFadeStartTime;
|
|
// if (diff > 0) {
|
|
// if (diff >= kOSDFadeOutDuration) {
|
|
// // Back to full transparency
|
|
// _osdAlpha = gpALPHA_TRANSPARENT;
|
|
// } else {
|
|
// // Do a linear fade out...
|
|
// const int startAlpha = gpALPHA_TRANSPARENT + kOSDInitialAlpha * (gpALPHA_OPAQUE - gpALPHA_TRANSPARENT) / 100;
|
|
// _osdAlpha = startAlpha + diff * (gpALPHA_TRANSPARENT - startAlpha) / kOSDFadeOutDuration;
|
|
// }
|
|
// gpSetAlpha(_osdSurface, gpRLEACCEL | gpSRCCOLORKEY | gpSRCALPHA, _osdAlpha);
|
|
// _forceFull = true;
|
|
// }
|
|
// }
|
|
//#endif
|
|
|
|
// Force a full redraw if requested
|
|
if (_forceFull) {
|
|
_num_dirty_rects = 1;
|
|
|
|
_dirty_rect_list[0].x = 0;
|
|
_dirty_rect_list[0].y = 0;
|
|
_dirty_rect_list[0].w = _screenWidth;
|
|
_dirty_rect_list[0].h = _screenHeight;
|
|
}
|
|
// Only draw anything if necessary
|
|
if (_num_dirty_rects > 0) {
|
|
|
|
gpRect *r;
|
|
gpRect dst;
|
|
uint32 srcPitch, dstPitch;
|
|
gpRect *last_rect = _dirty_rect_list + _num_dirty_rects;
|
|
|
|
if (_scaler_proc == Normal1x && !_adjustAspectRatio) {
|
|
|
|
gpSurface *target =
|
|
_overlayVisible ? _tmpscreen : _screen;
|
|
for (r = _dirty_rect_list; r != last_rect; ++r) {
|
|
dst = *r;
|
|
|
|
if (_overlayVisible) {
|
|
// FIXME: I don't understand why this is necessary...
|
|
dst.x--;
|
|
dst.y--;
|
|
}
|
|
dst.y += _currentShakePos;
|
|
if (gpBlitSurface(target, r, _hwscreen,
|
|
&dst) != 0)
|
|
error("gpBlitSurface failed: %s",
|
|
gpGetError());
|
|
}
|
|
} else {
|
|
if (!_overlayVisible) {
|
|
|
|
for (r = _dirty_rect_list; r != last_rect; ++r) {
|
|
dst = *r;
|
|
dst.x++; // Shift rect by one since 2xSai needs to acces the data around
|
|
dst.y++; // any pixel to scale it, and we want to avoid mem access crashes.
|
|
if (gpBlitSurface(_screen, r,
|
|
_tmpscreen, &dst) != 0)
|
|
error
|
|
("gpBlitSurface failed: %s",
|
|
gpGetError());
|
|
}
|
|
}
|
|
//gpLockSurface(_tmpscreen);
|
|
//gpLockSurface(_hwscreen);
|
|
|
|
srcPitch = _tmpscreen->pitch;
|
|
dstPitch = _hwscreen->pitch;
|
|
|
|
for (r = _dirty_rect_list; r != last_rect; ++r) {
|
|
|
|
register int dst_y = r->y + _currentShakePos;
|
|
register int dst_h = 0;
|
|
register int orig_dst_y = 0;
|
|
|
|
if (dst_y < _screenHeight) {
|
|
dst_h = r->h;
|
|
if (dst_h > _screenHeight - dst_y)
|
|
dst_h = _screenHeight - dst_y;
|
|
|
|
dst_y *= _scaleFactor;
|
|
|
|
if (_adjustAspectRatio) {
|
|
orig_dst_y = dst_y;
|
|
dst_y = real2Aspect(dst_y);
|
|
|
|
}
|
|
|
|
_scaler_proc((byte *) _tmpscreen->
|
|
pixels + (r->x * 2 + 2) + (r->y +
|
|
1) * srcPitch, srcPitch,
|
|
(byte *) _hwscreen->pixels +
|
|
r->x * 2 * _scaleFactor +
|
|
dst_y * dstPitch, dstPitch, r->w,
|
|
dst_h);
|
|
}
|
|
|
|
r->x *= _scaleFactor;
|
|
r->y = dst_y;
|
|
r->w *= _scaleFactor;
|
|
r->h = dst_h * _scaleFactor;
|
|
|
|
if (_adjustAspectRatio
|
|
&& orig_dst_y / _scaleFactor <
|
|
_screenHeight)
|
|
r->h =
|
|
stretch200To240((uint8 *)
|
|
_hwscreen->pixels, dstPitch, r->w,
|
|
r->h, r->x, r->y, orig_dst_y);
|
|
}
|
|
//gpUnlockSurface(_tmpscreen);
|
|
//gpUnlockSurface(_hwscreen);
|
|
|
|
}
|
|
|
|
// Readjust the dirty rect list in case we are doing a full update.
|
|
// This is necessary if shaking is active.
|
|
if (_forceFull) {
|
|
_dirty_rect_list[0].y = 0;
|
|
_dirty_rect_list[0].h = 240;
|
|
|
|
}
|
|
#ifdef USE_OSD
|
|
if (_osdAlpha != gpALPHA_TRANSPARENT) {
|
|
gpBlitSurface(_osdSurface, 0, _hwscreen, 0);
|
|
}
|
|
#endif
|
|
|
|
// Finally, blit all our changes to the screen
|
|
gpUpdateRects(_hwscreen, _num_dirty_rects, _dirty_rect_list);
|
|
|
|
}
|
|
|
|
_num_dirty_rects = 0;
|
|
_forceFull = false;
|
|
}
|
|
|
|
// assert(_hwscreen != NULL);
|
|
//
|
|
// // If the shake position changed, fill the dirty area with blackness
|
|
// if (_currentShakePos != _newShakePos) {
|
|
// gpRect blackrect = {0, 0, _screenWidth*_scaleFactor, _newShakePos*_scaleFactor};
|
|
// gpFillRect(_hwscreen, &blackrect, 0);
|
|
//
|
|
// _currentShakePos = _newShakePos;
|
|
//
|
|
// _forceFull = true;
|
|
// }
|
|
//
|
|
// // Make sure the mouse is drawn, if it should be drawn.
|
|
// draw_mouse(); //ph0x
|
|
//
|
|
// // Check whether the palette was changed in the meantime and update the
|
|
// // screen surface accordingly.
|
|
// if (_paletteDirtyEnd != 0) {
|
|
// gpSetColors(_screen, _currentPalette + _paletteDirtyStart,
|
|
// _paletteDirtyStart,
|
|
// _paletteDirtyEnd - _paletteDirtyStart);
|
|
//
|
|
// _paletteDirtyEnd = 0;
|
|
//
|
|
// _forceFull = true;
|
|
// }
|
|
//
|
|
// // Force a full redraw if requested
|
|
// if (_forceFull) {
|
|
// _num_dirty_rects = 1;
|
|
//
|
|
// _dirty_rect_list[0].x = 0;
|
|
// _dirty_rect_list[0].y = 0;
|
|
// _dirty_rect_list[0].w = _screenWidth;
|
|
// _dirty_rect_list[0].h = _screenHeight;
|
|
// }
|
|
//
|
|
// // Only draw anything if necessary
|
|
// if (_num_dirty_rects > 0) {
|
|
//
|
|
// gpRect *r;
|
|
// uint32 srcPitch, dstPitch;
|
|
// gpRect *last_rect = _dirty_rect_list + _num_dirty_rects;
|
|
//
|
|
// // Convert appropriate parts of the 8bpp image into 16bpp
|
|
// if (!_overlayVisible) {
|
|
// gpRect dst;
|
|
// for(r = _dirty_rect_list; r != last_rect; ++r) {
|
|
// dst = *r;
|
|
// dst.x++; // FIXME? Shift rect by one since 2xSai needs to acces the data around
|
|
// dst.y++; // FIXME? any pixel to scale it, and we want to avoid mem access crashes.
|
|
//
|
|
// if (gpBlitSurface(_screen, r, _hwscreen, &dst) != 0) //ph0x! gp_tmpscreen
|
|
// error("gpBlitSurface failed: %s", gpGetError());
|
|
// }
|
|
// }
|
|
//
|
|
// ///gp_LockSurface(gp_tmpscreen);
|
|
// ///gp_LockSurface(gp_hwscreen);
|
|
//
|
|
//// ph0x! (no scaling) cannot skip intro if commented?
|
|
//
|
|
// srcPitch = _tmpscreen->pitch;
|
|
// dstPitch = _hwscreen->pitch;
|
|
// for(r = _dirty_rect_list; r != last_rect; ++r) {
|
|
// register int dst_y = r->y + _currentShakePos;
|
|
// register int dst_h = 0;
|
|
// if (dst_y < _screenHeight) {
|
|
// dst_h = r->h;
|
|
// if (dst_h > _screenHeight - dst_y)
|
|
// dst_h = _screenHeight - dst_y;
|
|
//
|
|
// dst_y *= _scaleFactor;
|
|
//
|
|
// if (_overlayVisible) //ph0x fixme?
|
|
// _scaler_proc((byte*)_tmpscreen->pixels + (r->x*2+2) + (r->y+1)*srcPitch, srcPitch,
|
|
// (byte*)_hwscreen->pixels + r->x*2*_scaleFactor + dst_y*dstPitch, dstPitch, r->w, dst_h);
|
|
// }
|
|
// r->x *= _scaleFactor;
|
|
// r->y = dst_y;
|
|
// r->w *= _scaleFactor;
|
|
// r->h = dst_h * _scaleFactor;
|
|
// }
|
|
//
|
|
// ///gp_UnlockSurface(gp_tmpscreen);
|
|
// ///gp_UnlockSurface(gp_hwscreen);
|
|
//
|
|
// // Readjust the dirty rect list in case we are doing a full update.
|
|
// // This is necessary if shaking is active.
|
|
// if (_forceFull) {
|
|
// _dirty_rect_list[0].y = 0;
|
|
// _dirty_rect_list[0].h = _screenHeight * _scaleFactor;
|
|
// }
|
|
//
|
|
// // Finally, blit all our changes to the screen
|
|
//
|
|
// // FIXME (dont use condition)
|
|
// if (_overlayVisible)
|
|
// gpUpdateRects(_hwscreen, _num_dirty_rects, _dirty_rect_list); //ph0x! gp_hwscreen
|
|
// else
|
|
// gpUpdateRects(_screen, _num_dirty_rects, _dirty_rect_list);
|
|
// }
|
|
//
|
|
// _num_dirty_rects = 0;
|
|
// _forceFull = false;
|
|
//}
|
|
|
|
void OSystem_GP32::setFeatureState(Feature f, bool enable) {
|
|
|
|
switch (f) {
|
|
case kFeatureFullscreenMode:
|
|
setFullscreenMode(enable);
|
|
break;
|
|
case kFeatureAspectRatioCorrection:
|
|
if (_screenHeight == 200 && _adjustAspectRatio != enable) {
|
|
Common::StackLock lock(_graphicsMutex);
|
|
|
|
//assert(_hwscreen != 0);
|
|
_adjustAspectRatio ^= true;
|
|
hotswap_gfx_mode();
|
|
|
|
#ifdef USE_OSD
|
|
char buffer[128];
|
|
if (_adjustAspectRatio)
|
|
sprintf(buffer,
|
|
"Enabled aspect ratio correction\n%d x %d -> %d x %d",
|
|
_screenWidth, _screenHeight, _hwscreen->w,
|
|
_hwscreen->h);
|
|
else
|
|
sprintf(buffer,
|
|
"Disabled aspect ratio correction\n%d x %d -> %d x %d",
|
|
_screenWidth, _screenHeight, _hwscreen->w,
|
|
_hwscreen->h);
|
|
displayMessageOnOSD(buffer);
|
|
#endif
|
|
|
|
// Blit everything to the screen
|
|
internUpdateScreen();
|
|
|
|
// Make sure that an EVENT_SCREEN_CHANGED gets sent later
|
|
_modeChanged = true;
|
|
}
|
|
break;
|
|
case kFeatureAutoComputeDirtyRects:
|
|
if (enable)
|
|
_mode_flags |= DF_WANT_RECT_OPTIM;
|
|
else
|
|
_mode_flags &= ~DF_WANT_RECT_OPTIM;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
bool OSystem_GP32::hasFeature(Feature f) {
|
|
return false;
|
|
(f == kFeatureFullscreenMode) || (f == kFeatureAspectRatioCorrection);
|
|
// ||
|
|
// (f == kFeatureAutoComputeDirtyRects);
|
|
}
|
|
|
|
bool OSystem_GP32::getFeatureState(Feature f) {
|
|
|
|
switch (f) {
|
|
case kFeatureFullscreenMode:
|
|
return _full_screen;
|
|
case kFeatureAspectRatioCorrection:
|
|
return _adjustAspectRatio;
|
|
case kFeatureAutoComputeDirtyRects:
|
|
return _mode_flags & DF_WANT_RECT_OPTIM;
|
|
default:
|
|
return false;
|
|
}
|
|
}
|
|
|
|
void OSystem_GP32::setFullscreenMode(bool enable) {
|
|
Common::StackLock lock(_graphicsMutex);
|
|
|
|
if (_full_screen != enable) {
|
|
assert(_hwscreen != 0);
|
|
_full_screen ^= true;
|
|
undraw_mouse();
|
|
|
|
//if (!gpWM_ToggleFullScreen(_hwscreen)) {
|
|
// if ToggleFullScreen fails, achieve the same effect with hotswap gfx mode
|
|
// hotswap_gfx_mode();
|
|
//}
|
|
|
|
#ifdef USE_OSD
|
|
if (_full_screen)
|
|
displayMessageOnOSD("Fullscreen mode");
|
|
else
|
|
displayMessageOnOSD("Windowed mode");
|
|
#endif
|
|
|
|
// Blit everything to the screen
|
|
internUpdateScreen();
|
|
|
|
// Make sure that an EVENT_SCREEN_CHANGED gets sent later
|
|
_modeChanged = true;
|
|
}
|
|
}
|
|
|
|
static const OSystem::GraphicsMode supportedGraphicsModes[] = {
|
|
{"1x", "320x240 16bpp", GFX_NORMAL},
|
|
{0, 0, 0}
|
|
};
|
|
|
|
const OSystem::GraphicsMode *OSystem_GP32::getSupportedGraphicsModes() const {
|
|
return supportedGraphicsModes;
|
|
}
|
|
|
|
int OSystem_GP32::getDefaultGraphicsMode() const {
|
|
return GFX_NORMAL;
|
|
}
|
|
|
|
bool OSystem_GP32::setGraphicsMode(int mode) {
|
|
|
|
Common::StackLock lock(_graphicsMutex);
|
|
|
|
int newScaleFactor = 1;
|
|
ScalerProc *newScalerProc;
|
|
|
|
switch (mode) {
|
|
case GFX_NORMAL:
|
|
newScaleFactor = 1;
|
|
newScalerProc = Normal1x;
|
|
break;
|
|
//case GFX_DOUBLESIZE:
|
|
// newScaleFactor = 2;
|
|
// newScalerProc = Normal2x;
|
|
// break;
|
|
//case GFX_TRIPLESIZE:
|
|
// newScaleFactor = 3;
|
|
// newScalerProc = Normal3x;
|
|
// break;
|
|
//case GFX_2XSAI:
|
|
// newScaleFactor = 2;
|
|
// newScalerProc = _2xSaI;
|
|
// break;
|
|
//case GFX_SUPER2XSAI:
|
|
// newScaleFactor = 2;
|
|
// newScalerProc = Super2xSaI;
|
|
// break;
|
|
//case GFX_SUPEREAGLE:
|
|
// newScaleFactor = 2;
|
|
// newScalerProc = SuperEagle;
|
|
// break;
|
|
//case GFX_ADVMAME2X:
|
|
// newScaleFactor = 2;
|
|
// newScalerProc = AdvMame2x;
|
|
// break;
|
|
//case GFX_ADVMAME3X:
|
|
// newScaleFactor = 3;
|
|
// newScalerProc = AdvMame3x;
|
|
// break;
|
|
//case GFX_HQ2X:
|
|
// newScaleFactor = 2;
|
|
// newScalerProc = HQ2x;
|
|
// break;
|
|
//case GFX_HQ3X:
|
|
// newScaleFactor = 3;
|
|
// newScalerProc = HQ3x;
|
|
// break;
|
|
//case GFX_TV2X:
|
|
// newScaleFactor = 2;
|
|
// newScalerProc = TV2x;
|
|
// break;
|
|
//case GFX_DOTMATRIX:
|
|
// newScaleFactor = 2;
|
|
// newScalerProc = DotMatrix;
|
|
// break;
|
|
|
|
default:
|
|
warning("unknown gfx mode %d", mode);
|
|
return false;
|
|
}
|
|
|
|
_mode = mode;
|
|
_scaler_proc = newScalerProc;
|
|
if (newScaleFactor != _scaleFactor) {
|
|
_scaleFactor = newScaleFactor;
|
|
hotswap_gfx_mode();
|
|
}
|
|
|
|
if (!_screen)
|
|
return true;
|
|
|
|
#ifdef USE_OSD
|
|
if (_osdSurface) {
|
|
const char *newScalerName = 0;
|
|
const GraphicsMode *g = s_supportedGraphicsModes;
|
|
while (g->name) {
|
|
if (g->id == mode) {
|
|
newScalerName = g->description;
|
|
break;
|
|
}
|
|
g++;
|
|
}
|
|
if (newScalerName) {
|
|
char buffer[128];
|
|
sprintf(buffer,
|
|
"Active graphics filter: %s\n%d x %d -> %d x %d",
|
|
newScalerName, _screenWidth, _screenHeight,
|
|
_hwscreen->w, _hwscreen->h);
|
|
displayMessageOnOSD(buffer);
|
|
}
|
|
}
|
|
#endif
|
|
|
|
// Blit everything to the screen
|
|
_forceFull = true;
|
|
internUpdateScreen();
|
|
|
|
// Make sure that an EVENT_SCREEN_CHANGED gets sent later
|
|
_modeChanged = true;
|
|
|
|
return true;
|
|
}
|
|
|
|
int OSystem_GP32::getGraphicsMode() const {
|
|
return _mode;
|
|
}
|
|
|
|
////OSystem *OSystem_GP32::create(int gfx_mode, bool full_screen)
|
|
//OSystem *OSystem_GP32::create()
|
|
//{
|
|
// //OSystem_GP32 *syst = new OSystem_GP32();
|
|
//
|
|
// //syst->_mode = gfx_mode;
|
|
// //syst->_full_screen = full_screen;
|
|
// //
|
|
// //// allocate palette storage
|
|
// //syst->_currentPalette = (gpColor*)calloc(sizeof(gpColor), 256);
|
|
//
|
|
// //// allocate the dirty rect storage
|
|
// //syst->_mouseBackup = (byte*)malloc(MAX_MOUSE_W * MAX_MOUSE_H * MAX_SCALING * 2);
|
|
// /*return syst;*/
|
|
// return new OSystem_GP32();
|
|
//}
|
|
|
|
//////////////////////////////////////////////////
|
|
// GP32 stuff
|
|
//////////////////////////////////////////////////
|
|
|
|
extern "C" int write(int fd, void *p, size_t n);
|
|
int write(int fd, void *p, size_t n) { //ph0x hack!
|
|
return 0;
|
|
}
|
|
|
|
// Converts 8bit rgb values to a GP32 palette value
|
|
void GpSetPaletteEntry(u8 i, u8 r, u8 g, u8 b) {
|
|
GP_PALETTEENTRY entry = gpRGB16(r, g, b);
|
|
GpPaletteEntryChange(i, 1, &entry, 0);
|
|
}
|
|
|
|
int gpprintf(const char *fmt, ...) {
|
|
static bool busy;
|
|
static int y;
|
|
char s[1024]; // ?
|
|
va_list marker;
|
|
|
|
if (busy)
|
|
return 0;
|
|
busy = true;
|
|
va_start(marker, fmt);
|
|
vsprintf(s, fmt, marker);
|
|
va_end(marker);
|
|
|
|
#ifdef GPDEBUG
|
|
//dprintf("mem: %d ", gm_availablesize());
|
|
dprintf(s);
|
|
if (s[strlen(s) - 1] != '\n')
|
|
dprintf("\n");
|
|
//if (s[0]!='>') return r;
|
|
#endif
|
|
|
|
fprintf(stdout, s);
|
|
|
|
// print to lcd
|
|
GpTextOut(NULL, &LCDbuffer[DEBUG_SURFACE], 0, y, s, 1);
|
|
y += (ENGFONT_H - FONT_LINEGAP);
|
|
if (y >
|
|
(240 / (ENGFONT_H - FONT_LINEGAP)) * (ENGFONT_H - FONT_LINEGAP)) {
|
|
y = 0;
|
|
GpRectFill(NULL, &LCDbuffer[DEBUG_SURFACE], 0, 0, 320, 240, 2);
|
|
}
|
|
busy = false;
|
|
return 0;
|
|
}
|
|
|
|
int gpfprintf(FILE *stream, const char *fmt, ...) {
|
|
char s[256];
|
|
va_list marker;
|
|
|
|
va_start(marker, fmt);
|
|
vsprintf(s, fmt, marker);
|
|
va_end(marker);
|
|
|
|
return fwrite(s, 1, strlen(s), stream);
|
|
}
|
|
|
|
typedef struct {
|
|
FILE f;
|
|
ulong size;
|
|
ulong p; //cache position
|
|
} xfile;
|
|
|
|
#define XFILE(f) (*(xfile*)f)
|
|
#define FCACHE_SIZE 8*1024 // speed up writes
|
|
|
|
FILE *gpfopen(const char *filename, const char *mode) {
|
|
//FIXME: allocation, mode, malloc -> new
|
|
ulong m;
|
|
FILE *f;
|
|
ERR_CODE err;
|
|
char s[256];
|
|
|
|
if (!strchr(filename, '.')) {
|
|
sprintf(s, "%s.", filename);
|
|
filename = s;
|
|
}
|
|
//printf(">open %s as %s", filename, mode);
|
|
|
|
// FIXME add binary/text support
|
|
if (tolower(mode[0]) == 'r') {
|
|
f = (FILE *) malloc(sizeof(xfile));
|
|
m = OPEN_R;
|
|
GpFileGetSize(filename, &XFILE(f).size);
|
|
err = GpFileOpen(filename, m, f);
|
|
} else if (tolower(mode[0]) == 'w') {
|
|
//printf("open if as W");
|
|
f = (FILE *) malloc(sizeof(xfile) + FCACHE_SIZE);
|
|
XFILE(f).size = 0; // FIXME? new file has no size?
|
|
XFILE(f).p = 0;
|
|
m = OPEN_W;
|
|
err = GpFileCreate(filename, ALWAYS_CREATE, f);
|
|
} else
|
|
error("wrong file mode");
|
|
|
|
if (!f)
|
|
error("%s: cannot crate F_HANDLE", __FUNCTION__);
|
|
if (err) {
|
|
//printf("IOerr %d", err);
|
|
return NULL;
|
|
} else
|
|
return f;
|
|
}
|
|
|
|
int gpfclose(FILE *f) {
|
|
if (!f) {
|
|
//warning("closing null file");
|
|
return 1;
|
|
}
|
|
|
|
if (*(u32 *)((char *)f - sizeof(u32)) == 0x4321) {
|
|
debug(0, "Double closing", __FUNCTION__);
|
|
return 1;
|
|
} // return 1 ??
|
|
|
|
if (XFILE(f).p) {
|
|
GpFileWrite(*f, (char *)f + sizeof(xfile), XFILE(f).p); // flush cache
|
|
XFILE(f).p = 0;
|
|
}
|
|
|
|
ERR_CODE err = GpFileClose(*f);
|
|
free(f);
|
|
|
|
return err;
|
|
}
|
|
|
|
int gpfseek(FILE *stream, long offset, int whence) {
|
|
ulong dummy;
|
|
|
|
switch (whence) {
|
|
case SEEK_SET:
|
|
whence = FROM_BEGIN;
|
|
break;
|
|
case SEEK_CUR:
|
|
whence = FROM_CURRENT;
|
|
break;
|
|
case SEEK_END:
|
|
whence = FROM_END;
|
|
break;
|
|
}
|
|
return GpFileSeek(*stream, whence, offset, (long *)&dummy);
|
|
}
|
|
|
|
long gpftell(FILE *stream) { // fixme? use standard func
|
|
ulong pos = 0;
|
|
//ERR_CODE err = GpFileSeek(*stream, FROM_CURRENT, 0, (long*)&pos);
|
|
return pos;
|
|
}
|
|
|
|
size_t gpfread(void *ptr, size_t size, size_t n, FILE *stream) {
|
|
ulong readcount = 0;
|
|
//ERR_CODE err = GpFileRead(*stream, ptr, size*n, &readcount); //fixme? size*n
|
|
return readcount / size; //FIXME?
|
|
}
|
|
|
|
size_t gpfwrite(const void *ptr, size_t size, size_t n, FILE *f) {
|
|
int len = size * n;
|
|
|
|
if (!f) {
|
|
//warning("writing to null file");
|
|
return 0;
|
|
}
|
|
|
|
if (XFILE(f).p + len < FCACHE_SIZE) {
|
|
memcpy((char *)f + sizeof(xfile) + XFILE(f).p, ptr, len);
|
|
XFILE(f).p += len;
|
|
} else {
|
|
if (XFILE(f).p) {
|
|
GpFileWrite(*f, (char *)f + sizeof(xfile), XFILE(f).p); // flush cache
|
|
XFILE(f).p = 0;
|
|
}
|
|
|
|
ERR_CODE err = GpFileWrite(*f, ptr, len);
|
|
if (!err)
|
|
return n;
|
|
else
|
|
return -err;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
void gpclearerr(FILE *stream) {
|
|
//warning("fixme: %s", __FUNCTION__);
|
|
}
|
|
|
|
int gpfeof(FILE *f) { //fixme!
|
|
return ftell(f) >= XFILE(f).size;
|
|
}
|
|
|
|
char *gpfgets(char *s, int n, FILE *f) {
|
|
int i = 0;
|
|
|
|
while (!feof(f) && i < n) {
|
|
fread(&s[i], 1, 1, f);
|
|
if (s[i] == '\n') {
|
|
s[i + 1] = 0;
|
|
return s;
|
|
}
|
|
i++;
|
|
}
|
|
if (feof(f))
|
|
return NULL;
|
|
else
|
|
return s;
|
|
}
|
|
|
|
char gpfgetc(FILE *f) {
|
|
char c[1];
|
|
|
|
fread(&c[0], 1, 1, f);
|
|
return c[0];
|
|
}
|
|
|
|
int gpfflush(FILE * stream) {
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
* GP32 Memory managment.
|
|
*/
|
|
|
|
void *gpmalloc(size_t size) {
|
|
u32 np;
|
|
u32 *up;
|
|
|
|
np = (u32) gm_malloc(size + sizeof(u32));
|
|
|
|
if (np) {
|
|
up = (u32 *) np;
|
|
*up = 0x1234;
|
|
return (void *)(np + sizeof(u32));
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
void *gpcalloc(size_t nitems, size_t size) {
|
|
void *p = gpmalloc(nitems * size); //gpcalloc doesnt clear?
|
|
|
|
memset(p, 0, nitems * size);
|
|
if (*(u8 *) p)
|
|
warning("%s: calloc doesn't clear!", __FUNCTION__); //fixme: was error
|
|
//printf("callocing");
|
|
return p;
|
|
}
|
|
|
|
void gpfree(void *block) {
|
|
u32 np;
|
|
u32 *up;
|
|
|
|
if (!block) {
|
|
debug(0, "freeing null pointer");
|
|
return;
|
|
}
|
|
|
|
np = ((u32) block) - sizeof(u32);
|
|
up = (u32 *) np;
|
|
if (*up == 0x4321)
|
|
error("%s: double deallocation!", __FUNCTION__);
|
|
|
|
if (*up != 0x1234)
|
|
error("%s: corrupt block!", __FUNCTION__);
|
|
*up = 0x4321;
|
|
|
|
gm_free(up);
|
|
}
|
|
|
|
/*
|
|
char *gpstrdup(const char *s) {
|
|
char *p=(char*)malloc(strlen(s)+1);
|
|
memcpy(p, s, strlen(s)+1);
|
|
return p;
|
|
}
|
|
*/
|
|
|
|
char *gpstrdup(const char *strSource) {
|
|
char *strBuffer;
|
|
strBuffer = (char *)malloc(strlen(strSource) + 1);
|
|
if (strBuffer)
|
|
strcpy(strBuffer, strSource);
|
|
return strBuffer;
|
|
}
|
|
|
|
time_t gptime(time_t *timer) {
|
|
time_t t = GpTickCountGet() / 1000;
|
|
if (timer)
|
|
*timer = t;
|
|
return t;
|
|
}
|
|
|
|
void gpdeinit() {
|
|
fclose(fstdin);
|
|
fclose(fstdout);
|
|
fclose(fstderr);
|
|
}
|
|
|
|
void gpexit(int code) {
|
|
switchsurf(DEBUG_SURFACE);
|
|
|
|
if (!code) {
|
|
printf("----------------------------------------");
|
|
printf(" Your GP32 is now restarting... ");
|
|
printf("----------------------------------------");
|
|
|
|
gpdeinit();
|
|
|
|
// FIXME: use function :)
|
|
int n = GpTickCountGet();
|
|
while ((GpTickCountGet() - n) < 3000);
|
|
|
|
GpAppExit();
|
|
} else {
|
|
printf("Exit Code %d", code);
|
|
while (1);
|
|
}
|
|
}
|
|
|
|
/****************************************************************
|
|
Setup CPU Speed - Calls to CPUSPEED.S
|
|
****************************************************************/
|
|
void gpCPUSpeed(int freq) {
|
|
// To extend use: cpu_speed(CLK_SPEED, DIV_FACTOR, CLK_MODE);
|
|
if (freq == 166)
|
|
cpu_speed(165000000, 0x2f001, 3); // 40 Bus?
|
|
if (freq == 156)
|
|
cpu_speed(156000000, 0x2c001, 3); // 36 Bus
|
|
if (freq == 133)
|
|
cpu_speed(133500000, (81 << 12) | (2 << 4) | 1, 2); // 66 Bus?
|
|
if (freq == 132)
|
|
cpu_speed(132000000, 0x3a011, 3); // 33 Bus
|
|
if (freq == 120)
|
|
cpu_speed(120000000, 0x24001, 2);
|
|
if (freq == 100)
|
|
cpu_speed(102000000, (43 << 12) | (1 << 4) | 1, 2);
|
|
if (freq == 66)
|
|
cpu_speed(67500000, (37 << 12) | (0 << 4) | 2, 2);
|
|
if (freq == 40)
|
|
cpu_speed(40000000, 0x48013, 1); // Default
|
|
if (freq == 33)
|
|
cpu_speed(33750000, (37 << 12) | (0 << 4) | 3, 2); // Ultra slow
|
|
}
|
|
|
|
/****************************************************************
|
|
Pre-ScummVM Configuration Menu.
|
|
****************************************************************/
|
|
int ConfigMenu() {
|
|
//#ifndef GP32_GDB
|
|
// gpCPUSpeed(40);
|
|
//#endif /*GP32_GDB*/
|
|
|
|
GpSetPaletteEntry(2, 0, 0, 0);
|
|
GpSetPaletteEntry(1, 0, 0, 0);
|
|
GpSetPaletteEntry(0, 255, 255, 255);
|
|
|
|
int i, key, fg, bg, choice = 0, y = ENGFONT_H * 7;
|
|
int n = ARRAYSIZE(menu);
|
|
|
|
GpTextOut(NULL, &LCDbuffer[(int)currentsurf], 0, y,
|
|
"Configuration Menu", 1);
|
|
y += ENGFONT_H;
|
|
GpTextOut(NULL, &LCDbuffer[(int)currentsurf], 0, y,
|
|
"----------------------------------------", 1);
|
|
y += ENGFONT_H;
|
|
|
|
do {
|
|
for (i = 0; i < n; i++) {
|
|
if (i == choice) {
|
|
fg = 2;
|
|
bg = 1;
|
|
} else {
|
|
fg = 1;
|
|
bg = 2;
|
|
}
|
|
GpRectFill(NULL, &LCDbuffer[(int)currentsurf], 0,
|
|
y + i * ENGFONT_H, 320, ENGFONT_H, bg);
|
|
char s[256];
|
|
sprintf(s, "%s [%s]", menu[i].option,
|
|
menu[i].submenu[menu[i].index]);
|
|
GpTextOut(NULL, &LCDbuffer[(int)currentsurf], 0,
|
|
y + i * ENGFONT_H, s, fg);
|
|
}
|
|
|
|
do
|
|
key = gpTrapKey();
|
|
while (key == GPC_VK_NONE);
|
|
|
|
if (key & GPC_VK_DOWN) {
|
|
if (choice < n - 1)
|
|
choice++;
|
|
}
|
|
if (key & GPC_VK_UP) {
|
|
if (choice > 0)
|
|
choice--;
|
|
}
|
|
if (key & GPC_VK_LEFT) {
|
|
if (menu[choice].index > 0)
|
|
menu[choice].index--;
|
|
}
|
|
if (key & GPC_VK_RIGHT) {
|
|
if (menu[choice].submenu[menu[choice].index + 1])
|
|
menu[choice].index++;
|
|
}
|
|
//if (key & GPC_VK_START || key & GPC_VK_FA) return 1;
|
|
if (key & GPC_VK_FA)
|
|
return 1;
|
|
//if (key & GPC_VK_SELECT) return 0;
|
|
|
|
do
|
|
key = gpTrapKey();
|
|
while (key != GPC_VK_NONE);
|
|
|
|
} while (1);
|
|
}
|
|
|
|
/****************************************************************
|
|
Delay (very simple delay)
|
|
****************************************************************/
|
|
void Delay(unsigned int ms) {
|
|
unsigned int delay_by;
|
|
delay_by = GpTickCountGet();
|
|
while (GpTickCountGet() - delay_by < ms);
|
|
}
|
|
|
|
/****************************************************************
|
|
Triple buffering code
|
|
****************************************************************/
|
|
void FlipScreen() {
|
|
if (nflip == 0) {
|
|
GpSurfaceFlip(&LCDbuffer[0]);
|
|
nflip = 1;
|
|
} else if (nflip == 1) {
|
|
GpSurfaceFlip(&LCDbuffer[1]);
|
|
nflip = 2;
|
|
} else if (nflip == 2) {
|
|
GpSurfaceFlip(&LCDbuffer[2]);
|
|
nflip = 0;
|
|
}
|
|
}
|
|
|
|
/****************************************************************
|
|
Clear all the screen buffers
|
|
****************************************************************/
|
|
void ClearScreen() {
|
|
int i;
|
|
for (i = 0; i <= BUFFERCOUNT; i++) {
|
|
GpRectFill(NULL, &LCDbuffer[i], 0, 0, LCDbuffer[i].buf_w,
|
|
LCDbuffer[i].buf_h, 0x00);
|
|
}
|
|
}
|
|
|
|
/****************************************************************
|
|
Fade to black
|
|
****************************************************************/
|
|
void FadeToBlack(int delay_time) {
|
|
//Fade to black
|
|
int x;
|
|
for (x = 0; x < 30; x++) {
|
|
//Fade it further
|
|
GpLcdFade(-1, NULL);
|
|
|
|
//refresh screen
|
|
GpSurfaceFlip(&LCDbuffer[nflip]);
|
|
|
|
//wait a littel bit
|
|
Delay(delay_time);
|
|
}
|
|
|
|
//Now Clear all the buffers
|
|
ClearScreen();
|
|
|
|
//Turn the fading off
|
|
GpLcdNoFade(NULL);
|
|
|
|
//Now flip to end it all and leave it black
|
|
FlipScreen();
|
|
}
|
|
|
|
/****************************************************************
|
|
Fade to White
|
|
****************************************************************/
|
|
void FadeToWhite(int delay_time) {
|
|
//Fade to black
|
|
int x;
|
|
for (x = 0; x < 30; x++) {
|
|
//Fade it further
|
|
GpLcdFade(1, NULL);
|
|
|
|
//refresh screen
|
|
GpSurfaceFlip(&LCDbuffer[nflip]);
|
|
|
|
//wait a littel bit
|
|
Delay(delay_time);
|
|
}
|
|
|
|
//Now Clear all the buffers
|
|
ClearScreen();
|
|
|
|
//Turn the fading off
|
|
GpLcdNoFade(NULL);
|
|
|
|
//Now flip to end it all and leave it black
|
|
FlipScreen();
|
|
}
|
|
|
|
/****************************************************************
|
|
Initialise the File System
|
|
****************************************************************/
|
|
void InitFileSystem() {
|
|
//Initialises GP32 file system
|
|
GpFatInit();
|
|
GpRelativePathSet("gp:\\gpmm");
|
|
|
|
// Create folders on SMC if there not there
|
|
// For storing games, saves, config and scummvm.ini.
|
|
GpDirCreate("gp:\\data", NOT_IF_EXIST);
|
|
GpDirCreate("gp:\\data\\scummvm", NOT_IF_EXIST);
|
|
GpDirCreate("gp:\\data\\scummvm\\games", NOT_IF_EXIST);
|
|
GpDirCreate("gp:\\data\\scummvm\\config", NOT_IF_EXIST);
|
|
}
|
|
|
|
/****************************************************************
|
|
Splash Screen - show splash screen
|
|
****************************************************************/
|
|
|
|
void InitSplashPal() {
|
|
static GP_HPALETTE h_splash_pal = NULL;
|
|
if (h_splash_pal)
|
|
GpPaletteDelete(h_splash_pal);
|
|
h_splash_pal = GpPaletteCreate(gfx_splash_palnb, gfx_splash_Pal);
|
|
GpPaletteDelete(GpPaletteSelect(h_splash_pal));
|
|
GpPaletteRealize();
|
|
}
|
|
|
|
int SplashScreen() {
|
|
int key;
|
|
|
|
ClearScreen();
|
|
InitSplashPal();
|
|
|
|
// Show the screen (load into all buffers - ready for screen transition)
|
|
GpBitBlt(NULL, &LCDbuffer[0], 0, 0, gfx_splash_width,
|
|
gfx_splash_height, (unsigned char *)gfx_splash, 0, 0,
|
|
gfx_splash_width, gfx_splash_height);
|
|
GpBitBlt(NULL, &LCDbuffer[1], 0, 0, gfx_splash_width,
|
|
gfx_splash_height, (unsigned char *)gfx_splash, 0, 0,
|
|
gfx_splash_width, gfx_splash_height);
|
|
GpBitBlt(NULL, &LCDbuffer[2], 0, 0, gfx_splash_width,
|
|
gfx_splash_height, (unsigned char *)gfx_splash, 0, 0,
|
|
gfx_splash_width, gfx_splash_height);
|
|
|
|
// Refresh screen (show the logo)
|
|
FlipScreen();
|
|
|
|
// Initialise the File System
|
|
// Done during SpashScreen to hide folder create (if needed) from users.
|
|
InitFileSystem();
|
|
|
|
//TODO: Put branchs for Start and Select and act accordingly.
|
|
|
|
do {
|
|
do
|
|
key = gpTrapKey();
|
|
while (key == GPC_VK_NONE);
|
|
if (key & GPC_VK_START) {
|
|
FadeToBlack(20);
|
|
return 0;
|
|
}
|
|
if (key & GPC_VK_SELECT) {
|
|
FadeToWhite(20);
|
|
ConfigMenu();
|
|
return 0;
|
|
}
|
|
do
|
|
key = gpTrapKey();
|
|
while (key != GPC_VK_NONE);
|
|
} while (1);
|
|
|
|
//Fade the screen into GP32 setup or ScummVM.
|
|
//FadeToWhite(100);
|
|
}
|
|
|
|
/****************************************************************
|
|
Read and write the GP32 config file to the SMC
|
|
****************************************************************/
|
|
void ConfigRead() {
|
|
FILE *f;
|
|
|
|
f = fopen("gp:\\data\\scummvm\\config\\config.dat", "r");
|
|
|
|
if (f) {
|
|
for (unsigned int i = 0; i < ARRAYSIZE(menu); i++)
|
|
fread(&menu[i].index, 1, sizeof(menu[i].index), f);
|
|
fclose(f);
|
|
}
|
|
}
|
|
|
|
void ConfigWrite() {
|
|
FILE *f;
|
|
|
|
f = fopen("gp:\\data\\scummvm\\config\\config.dat", "w");
|
|
|
|
if (f) {
|
|
for (unsigned int i = 0; i < ARRAYSIZE(menu); i++)
|
|
fwrite(&menu[i].index, 1, sizeof(menu[i].index), f);
|
|
fclose(f);
|
|
}
|
|
}
|
|
|
|
/****************************************************************
|
|
Prepare GP32
|
|
****************************************************************/
|
|
void InitLCD() {
|
|
// Initialize graphics
|
|
GpGraphicModeSet(COLOUR_8BIT_MODE, NULL);
|
|
|
|
// Set the current buffer
|
|
nflip = 0;
|
|
|
|
short i;
|
|
for (i = 0; i <= BUFFERCOUNT; i++) {
|
|
GpLcdSurfaceGet(&LCDbuffer[i], i);
|
|
}
|
|
}
|
|
|
|
void Init() {
|
|
// Setup the LCD.
|
|
InitLCD();
|
|
|
|
// Load the Splash Screen and give the option of config or ScummVM.
|
|
// also sets up file system.
|
|
SplashScreen();
|
|
|
|
//GpSetPaletteEntry ( 2, 0,0,0 );
|
|
//GpSetPaletteEntry ( 1, 0,0,0 );
|
|
//GpSetPaletteEntry ( 0, 255,255,255 );
|
|
|
|
//// fixme - use get function
|
|
////currentsurf=DEBUG_SURFACE;
|
|
////GpSurfaceSet(&LCDbuffer[(int)currentsurf]);
|
|
//GpSurfaceSet(&LCDbuffer[nflip]);
|
|
//GpLcdEnable();
|
|
|
|
//stderr = fstdout = fopen("gp:\\data\\scummvm\\config\\debug.out", "w");
|
|
//stdin = NULL; //fixme?
|
|
////fstdin = fopen("stdin", "w");
|
|
////fstderr = fopen("stderr", "w");
|
|
|
|
//printf(" ScummVM for the GP32");
|
|
//printf("----------------------------------------");
|
|
//printf("PRIVATE BUILD - DO NOT PASS ON!");
|
|
//printf("ScummVM (c) 2001-4 The ScummVM Team");
|
|
//printf("GP32 Backend (c) 2004 by DJWillis");
|
|
//printf("Compiled %s, %s", __DATE__, __TIME__);
|
|
//printf("----------------------------------------");
|
|
//printf(" Press 'A' to Start ScummVM");
|
|
//printf("----------------------------------------");
|
|
|
|
///*
|
|
//ERR_CODE err;
|
|
//
|
|
//unsigned long bad;
|
|
//err = GpFormat("gp:", FORMAT_RESCUE, &bad);
|
|
//char s[256];
|
|
//GpRelativePathGet(s);
|
|
//*/
|
|
}
|
|
|
|
//void *gpmemset (void *s, int c, size_t n) {
|
|
// for (int i=n-1; i>=0; i--)
|
|
// ((char*)s)[i]=(char)c;
|
|
//}
|
|
//
|
|
//void *gpmemcpy (void *dest, const void *src, size_t n) {
|
|
// for (int i=n-1; i>=0; i--)
|
|
// ((char*)dest)[i]=((char*)src)[i];
|
|
//}
|
|
|
|
void buildgammatab(int val) {
|
|
float g = 1;
|
|
for (int i = 0; i < 256; i++) {
|
|
gammatab[255 - i] = g;
|
|
g *= scrGamma[val];
|
|
}
|
|
}
|
|
|
|
void buildgammatab2(int val) {
|
|
float g = 1;
|
|
for (int i = 0; i < 256; i++) {
|
|
gammatab2[255 - i] = g;
|
|
g *= scrGamma[val];
|
|
}
|
|
}
|
|
|
|
int stricmp(const char *string1, const char *string2) {
|
|
char src[4096];
|
|
char dest[4096];
|
|
int i;
|
|
|
|
for (i = 0; i < strlen(string1); i++)
|
|
if (string1[i] >= 'A' && string1[i] <= 'Z')
|
|
src[i] = string1[i] + 32;
|
|
else
|
|
src[i] = string1[i];
|
|
src[i] = 0;
|
|
|
|
for (i = 0; i < strlen(string2); i++)
|
|
if (string2[i] >= 'A' && string2[i] <= 'Z')
|
|
dest[i] = string2[i] + 32;
|
|
else
|
|
dest[i] = string2[i];
|
|
dest[i] = 0;
|
|
|
|
return strcmp(src, dest);
|
|
}
|
|
|
|
int strnicmp(const char *string1, const char *string2, int len) {
|
|
char src[4096];
|
|
char dest[4096];
|
|
int i;
|
|
|
|
for (i = 0; i < strlen(string1) && i < len; i++)
|
|
if (string1[i] >= 'A' && string1[i] <= 'Z')
|
|
src[i] = string1[i] + 32;
|
|
else
|
|
src[i] = string1[i];
|
|
src[i] = 0;
|
|
|
|
for (i = 0; i < strlen(string2) && i < len; i++)
|
|
if (string2[i] >= 'A' && string2[i] <= 'Z')
|
|
dest[i] = string2[i] + 32;
|
|
else
|
|
dest[i] = string2[i];
|
|
dest[i] = 0;
|
|
|
|
return strncmp(src, dest, len);
|
|
}
|
|
|
|
extern "C" void GpMain(void *arg);
|
|
extern "C" int scummvm_main(int argc, char *argv[]);
|
|
|
|
void GpMain(void *arg) {
|
|
|
|
#ifdef GP32_GDB
|
|
OpenUSB();
|
|
InstallISR();
|
|
#endif /*GP32_GDB */
|
|
|
|
// Wank up the GP32 good and propper ;-)
|
|
// asm volatile(" \n"
|
|
//" mov r0, #0x01 \n"
|
|
//" ldr r1, [r0] \n"
|
|
|
|
//" \n"
|
|
//:
|
|
//:
|
|
//:"r0", "r1");
|
|
|
|
// FIXME: causes crash?! (if not at first line of gpmain())
|
|
buildgammatab(gindex);
|
|
buildgammatab2(ARRAYSIZE(scrGamma) - 1);
|
|
|
|
Init();
|
|
|
|
// ConfigRead();
|
|
|
|
//if ()
|
|
//{
|
|
// ConfigWrite();
|
|
//}
|
|
|
|
//ConfigMenu();
|
|
//ConfigWrite();
|
|
|
|
// fixme - use get function
|
|
|
|
//currentsurf=GAME_SURFACE;
|
|
//GpSurfaceFlip(&LCDbuffer[(int)currentsurf]);
|
|
|
|
#ifndef GP32_GDB
|
|
int CPUSpeed =
|
|
atoi((const char *)menu[MENU_CPUSPEED].submenu[menu[MENU_CPUSPEED].
|
|
index]);
|
|
#endif /*GP32_GDB */
|
|
|
|
//static char *argv[] = { "scummvm", NULL, NULL, NULL };
|
|
// char *argv[] = { "scummvm", (char*)menu[MENU_MUSICDRV].submenu[menu[MENU_MUSICDRV].index]};
|
|
// static int argc = 4;
|
|
|
|
// Game Testing...
|
|
//int argc = 2;
|
|
//int argc = 4; char *argv[] = { "scummvm", "-enull", "-pgp:\\gpmm\\scummvm\\sky\\", "sky" };
|
|
int argc = 4;
|
|
char *argv[] = { "scummvm", "-enull", "", "" };
|
|
|
|
while (1) {
|
|
// Only set the CPU speed if the GDB Stub is NOT needed.
|
|
// No point calling ClearScreen(); as we want to see any odd stuff.
|
|
#ifndef GP32_GDB
|
|
gpCPUSpeed(CPUSpeed);
|
|
ClearScreen();
|
|
#endif /*GP32_GDB */
|
|
|
|
//FadeToWhite(200);
|
|
//exit(scummvm_main(argc, argv));
|
|
////////////////cast_argv = f(const_cast<double&>(d));
|
|
//////////////char* argv_;
|
|
////////////// argv_ = const_cast<*char*>(argv);
|
|
scummvm_main(argc, argv);
|
|
}
|
|
}
|