[Scummvm-cvs-logs] CVS: scummvm/backends/ps2 READ_PS2.TXT,1.1,1.2 DmaPipe.cpp,1.5,1.6 DmaPipe.h,1.4,1.5 Gs2dScreen.cpp,1.6,1.7 Gs2dScreen.h,1.6,1.7 GsDefs.h,1.5,1.6 asyncfio.cpp,1.6,1.7 asyncfio.h,1.5,1.6 fileio.cpp,1.5,1.6 fileio.h,1.6,1.7 icon.cpp,1.4,1.5 ps2input.cpp,1.5,1.6 ps2input.h,1.4,1.5 ps2pad.cpp,1.6,1.7 ps2pad.h,1.4,1.5 savefile.cpp,1.7,1.8 savefile.h,1.6,1.7 sysdefs.h,1.4,1.5 systemps2.cpp,1.9,1.10 systemps2.h,1.8,1.9 smushio.cpp,1.3,NONE

Robert Göffringmann lavosspawn at users.sourceforge.net
Wed Nov 9 11:53:01 CET 2005


Update of /cvsroot/scummvm/scummvm/backends/ps2
In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv24828/backends/ps2

Modified Files:
	DmaPipe.cpp DmaPipe.h Gs2dScreen.cpp Gs2dScreen.h GsDefs.h 
	asyncfio.cpp asyncfio.h fileio.cpp fileio.h icon.cpp 
	ps2input.cpp ps2input.h ps2pad.cpp ps2pad.h savefile.cpp 
	savefile.h sysdefs.h systemps2.cpp systemps2.h 
Added Files:
	READ_PS2.TXT 
Removed Files:
	smushio.cpp 
Log Message:
sync HEAD with 0-8-0 branch.


Index: DmaPipe.cpp
===================================================================
RCS file: /cvsroot/scummvm/scummvm/backends/ps2/DmaPipe.cpp,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -d -r1.5 -r1.6
--- DmaPipe.cpp	18 Oct 2005 01:30:14 -0000	1.5
+++ DmaPipe.cpp	9 Nov 2005 19:51:57 -0000	1.6
@@ -169,7 +169,7 @@
 void DmaPipe::flatRect(const GsVertex *p1, const GsVertex *p2, uint32 rgba) {
 	checkSpace(3);
 	_pipes[_curPipe]->setGifRegListTag( 4, 0xffffffffffff5510);
-	_pipes[_curPipe]->setListReg( GS_SET_PRIM(PR_SPRITE, 0, 0, 0, 0, 0, 0, 0, 0),
+	_pipes[_curPipe]->setListReg( GS_SET_PRIM(PR_SPRITE, 0, 0, 0, 1, 0, 0, 0, 0),
 								  GS_SET_COLQ(rgba));
 	_pipes[_curPipe]->setListReg( GS_SET_XYZ(p1->x, p1->y, p1->z),
 								  GS_SET_XYZ(p2->x, p2->y, p2->z));


Index: Gs2dScreen.cpp
===================================================================
RCS file: /cvsroot/scummvm/scummvm/backends/ps2/Gs2dScreen.cpp,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -d -r1.6 -r1.7
--- Gs2dScreen.cpp	18 Oct 2005 01:30:14 -0000	1.6
+++ Gs2dScreen.cpp	9 Nov 2005 19:51:57 -0000	1.7
@@ -28,13 +28,17 @@
 #include <math.h>
 #include "DmaPipe.h"
 #include "GsDefs.h"
+#include "graphics/surface.h"
 
 enum Buffers {
 	SCREEN = 0,
 	MOUSE,
-	TEXT
+	TEXT,
+	PRINTF
 };
 
+#define ANIM_STACK_SIZE (1024 * 32)
+
 #define DEFAULT_PAL_X		175
 #define DEFAULT_PAL_Y		60
 #define DEFAULT_NTSC_X		165
@@ -50,8 +54,6 @@
 #define M_SIZE 128
 #define M_POW 7
 
-#define PI 3.1415926535897932384626433832795
-
 static volatile uint32 g_VblankCmd = 0, g_DmacCmd = 0;
 static int g_VblankSema, g_DmacSema, g_AnimSema;
 static bool g_RunAnim = false;
@@ -60,8 +62,13 @@
 	{ SCALE(1), SCALE(1) },
 	{ SCALE(M_SIZE), SCALE(M_SIZE) }
 };
+static TexVertex kPrintTex[2] = {
+	{ SCALE(1), SCALE(1) },
+	{ SCALE(320), SCALE(200) }
+};
 
 void sioprintf(const char *zFormat, ...);
+void runAnimThread(Gs2dScreen *param);
 
 int vblankStartHandler(int cause) {
 	// start of VBlank period
@@ -92,6 +99,7 @@
 
 Gs2dScreen::Gs2dScreen(uint16 width, uint16 height, TVMode tvMode) {
 
+	_systemQuit = false;
 	ee_sema_t newSema;
 	newSema.init_count = 1;
 	newSema.max_count = 1;
@@ -103,9 +111,9 @@
 	g_AnimSema = CreateSema(&newSema);
 	assert((g_VblankSema >= 0) && (g_DmacSema >= 0) && (_screenSema >= 0) && (g_AnimSema >= 0));
 
-	AddIntcHandler(INT_VBLANK_START, vblankStartHandler, 0);
-	AddIntcHandler(INT_VBLANK_END, vblankEndHandler, 0);
-	AddDmacHandler(2, dmacHandler, 0);
+	_vblankStartId = AddIntcHandler(INT_VBLANK_START, vblankStartHandler, 0);
+	_vblankEndId   = AddIntcHandler(INT_VBLANK_END, vblankEndHandler, 0);
+	_dmacId		   = AddDmacHandler(2, dmacHandler, 0);
 
 	_dmaPipe = new DmaPipe(0x2000);
 
@@ -123,6 +131,7 @@
 
 	memset(_screenBuf, 0, _width * _height);
 	memset(_clut, 0, 256 * sizeof(uint32));
+	_clut[1] = GS_RGBA(0xC0, 0xC0, 0xC0, 0);
 	clearOverlay();
 
 	if (tvMode == TV_DONT_CARE) {
@@ -159,10 +168,11 @@
 	_clutPtrs[MOUSE]  = _clutPtrs[SCREEN] + 0x1000; // the cluts in PSMCT32 take up half a memory page each
 	_clutPtrs[TEXT]   = _clutPtrs[SCREEN] + 0x2000;
 	_texPtrs[SCREEN]  = _clutPtrs[SCREEN] + 0x3000;
-	_texPtrs[TEXT]    = 0;
-	_texPtrs[MOUSE]	  = 128 * 128 * 4;			  // mouse cursor is loaded into the gaps of the frame buffer
+	_texPtrs[TEXT]    = 0;						  // these buffers are stored in the alpha gaps of the frame buffers
+	_texPtrs[MOUSE]	  = 128 * 256 * 4;			  
+	_texPtrs[PRINTF]  = _texPtrs[MOUSE] + M_SIZE * M_SIZE * 4;
 
-	_showOverlay = true;
+	_showOverlay = false;
 	_showMouse = false;
 	_mouseScaleX = (_tvWidth << 8) / _width;
 	_mouseScaleY = (_tvHeight << 8) / _height;
@@ -173,7 +183,6 @@
 	// setup hardware now.
 	GS_CSR = CSR_RESET; // Reset GS
 	asm ("sync.p");
-
 	GS_CSR = 0;
 	GsPutIMR(0x7F00);
 
@@ -205,14 +214,55 @@
 
 	_clutChanged = _screenChanged = _overlayChanged = true;
 
+	clearPrintfOverlay();
 	updateScreen();
 
 	createAnimTextures();
-	createAnimThread(this);
+	
+	// create anim thread
+	ee_thread_t animThread, thisThread;
+	ReferThreadStatus(GetThreadId(), &thisThread);
+
+	_animStack = malloc(ANIM_STACK_SIZE);
+	animThread.initial_priority = thisThread.current_priority - 3;
+	animThread.stack = _animStack;
+	animThread.stack_size = ANIM_STACK_SIZE;
+	animThread.func = (void *)runAnimThread;
+	asm("move %0, $gp\n": "=r"(animThread.gp_reg));
+
+	_animTid = CreateThread(&animThread);
+	assert(_animTid >= 0);
+	StartThread(_animTid, this);
+}
+
+void Gs2dScreen::quit(void) {
+	_systemQuit = true;
+	ee_thread_t statAnim;
+	do {	// wait until thread called ExitThread()
+		SignalSema(g_AnimSema);
+		ReferThreadStatus(_animTid, &statAnim);
+	} while (statAnim.status != 0x10);
+	DeleteThread(_animTid);
+	free(_animStack);
+	_dmaPipe->waitForDma();	// wait for dmac and vblank for the last time
+	while (g_DmacCmd || g_VblankCmd);
+
+	sioprintf("kill handlers");
+	DisableIntc(INT_VBLANK_START);
+	DisableIntc(INT_VBLANK_END);
+	DisableDmac(2);
+	RemoveIntcHandler(INT_VBLANK_START, _vblankStartId);
+	RemoveIntcHandler(INT_VBLANK_END, _vblankEndId);
+	RemoveDmacHandler(2, _dmacId);
+
+	DeleteSema(g_VblankSema);
+	DeleteSema(g_DmacSema);
+	DeleteSema(g_AnimSema);
 }
 
 void Gs2dScreen::createAnimTextures(void) {
-	uint8 *buf = (uint8*)memalign(64, 14 * 64);
+	uint8 *buf = (uint8*)memalign(64, 16 * 64);
+	memset(buf, 0, 16 * 64);
 	uint32 vramDest = _texPtrs[TEXT];
 	for (int i = 0; i < 16; i++) {
 		uint32 *destPos = (uint32*)buf;
@@ -223,9 +273,9 @@
 			destPos++;
 		}
 		if (!(i & 1))
-			_dmaPipe->uploadTex( vramDest, 128, 0, 0,  GS_PSMT4HH, buf, 128, 14);
+			_dmaPipe->uploadTex( vramDest, 128, 0, 0,  GS_PSMT4HH, buf, 128, 16);
 		else {
-			_dmaPipe->uploadTex( vramDest, 128, 0, 0,  GS_PSMT4HL, buf, 128, 14);
+			_dmaPipe->uploadTex( vramDest, 128, 0, 0,  GS_PSMT4HL, buf, 128, 16);
 			vramDest += 128 * 16 * 4;
 		}
 		_dmaPipe->flush();
@@ -244,7 +294,6 @@
 	WaitSema(g_VblankSema);
 
 	_dmaPipe->flush();
-	_screenChanged = _overlayChanged = false;
 	_width = width;
 	_height = height;
 	_pitch = (width + 127) & ~127;
@@ -277,16 +326,41 @@
 	SignalSema(g_DmacSema);
 }
 
-void Gs2dScreen::copyScreenRect(const uint8 *buf, uint16 pitch, uint16 x, uint16 y, uint16 w, uint16 h) {
-	assert((x + w <= _width) && (y + h <= _height));
+void Gs2dScreen::copyScreenRect(const uint8 *buf, int pitch, int x, int y, int w, int h) {
+	if (x < 0) {
+		w += x;
+		buf -= x;
+		x = 0;
+	}
+	if (y < 0) {
+		h += y;
+		buf -= y * pitch;
+		y = 0;
+	}
+	if (x + w > _width)
+		w = (int)_width - x;
+	if (y + h > _height)
+		h = (int)_height - y;
 
-	WaitSema(g_DmacSema);
-	uint8 *dest = _screenBuf + y * _width + x;
-	for (uint16 cnt = 0; cnt < h; cnt++) {
-		memcpy(dest, buf, w);
-		buf += pitch;
-		dest += _width;
+	if ((w > 0) && (h > 0)) {
+		WaitSema(g_DmacSema);
+		uint8 *dest = _screenBuf + y * _width + x;
+		if ((w == pitch) && (pitch == _width))
+			memcpy(dest, buf, w * h);
+		else
+			for (int cnt = 0; cnt < h; cnt++) {
+				memcpy(dest, buf, w);
+				buf += pitch;
+				dest += _width;
+			}
+		_screenChanged = true;
+		SignalSema(g_DmacSema);
 	}
+}
+
+void Gs2dScreen::clearScreen(void) {
+	WaitSema(g_DmacSema);
+	memset(_screenBuf, 0, _width * _height);
 	_screenChanged = true;
 	SignalSema(g_DmacSema);
 }
@@ -313,9 +387,15 @@
 	}
 }
 
-void Gs2dScreen::updateScreen(void) {
-	WaitSema(_screenSema);
+void Gs2dScreen::grabScreen(Graphics::Surface *surf) {
+	assert(surf);
+	WaitSema(g_DmacSema);
+	surf->create(_width, _height, 1);
+	memcpy(surf->pixels, _screenBuf, _width * _height);
+	SignalSema(g_DmacSema);
+}
 
+void Gs2dScreen::uploadToVram(void) {
 	if (_clutChanged) {
 		_clutChanged = false;
 		uint32 tmp = _clut[_mTraCol];
@@ -328,43 +408,73 @@
 		_dmaPipe->uploadTex(_clutPtrs[SCREEN], 64, 0, 0, GS_PSMCT32, _clut, 16, 16);
 	}
 
-	_dmaPipe->flatRect(kFullScreen + 0, kFullScreen + 1, GS_RGBA(0, 0, 0, 0)); // clear screen
-
 	if (_showOverlay) {
 		if (_overlayChanged) {
 			_dmaPipe->uploadTex(_texPtrs[SCREEN], _width, 0, 0, GS_PSMCT16, _overlayBuf, _width, _height);
 			_overlayChanged = false;
 		}
-		_dmaPipe->setTex(_texPtrs[SCREEN], _width, TEX_POW, TEX_POW, GS_PSMCT16, 0, 0, 0, 0);
-		_dmaPipe->textureRect(kFullScreen + 0, kFullScreen + 1, _texCoords + 0, _texCoords + 1);
 	} else {
 		if (_screenChanged) {
 			_dmaPipe->uploadTex(_texPtrs[SCREEN], _pitch, 0, 0, GS_PSMT8, _screenBuf, _width, _height);
 			_screenChanged = false;
 		}
-		_dmaPipe->setTex(_texPtrs[SCREEN], _pitch, TEX_POW, TEX_POW, GS_PSMT8, _clutPtrs[SCREEN], 0, 64, GS_PSMCT32);
-		_dmaPipe->textureRect(_blitCoords + 0, _blitCoords + 1, _texCoords + 0, _texCoords + 1);
 	}
+}
 
-	if (_showMouse) {
-		GsVertex mouseCoords[2];
-		mouseCoords[0].x = (((_mouseX - _hotSpotX) * _mouseScaleX + 8) >> 4) + ORIGIN_X;
-		mouseCoords[0].y = (((_mouseY - _hotSpotY) * _mouseScaleY + 8) >> 4) + ORIGIN_Y;
-		mouseCoords[1].x = mouseCoords[0].x + (((M_SIZE * _mouseScaleX) + 8) >> 4);
-		mouseCoords[1].y = mouseCoords[0].y + (((M_SIZE * _mouseScaleY) + 8) >> 4);
-		mouseCoords[0].z = mouseCoords[1].z = 0;
+extern "C" void _ps2sdk_alloc_lock(void);
+extern "C" void _ps2sdk_alloc_unlock(void);
 
-		_dmaPipe->setTex(_texPtrs[MOUSE], M_SIZE, M_POW, M_POW, GS_PSMT8H, _clutPtrs[MOUSE], 0, 64, GS_PSMCT32);
-		_dmaPipe->textureRect(mouseCoords + 0, mouseCoords + 1, kMouseTex + 0, kMouseTex + 1);
-	}
+void Gs2dScreen::updateScreen(void) {
+	WaitSema(_screenSema);
+	uploadToVram();
+	if (!g_RunAnim) {
+		_dmaPipe->flatRect(kFullScreen + 0, kFullScreen + 1, GS_RGBA(0, 0, 0, 0)); // clear screen
 
-	WaitSema(g_DmacSema);	// wait for dma transfer, if there's one running
-	WaitSema(g_VblankSema); // wait if there's already an image waiting for vblank
+		if (_showOverlay) {
+			_dmaPipe->setTex(_texPtrs[SCREEN], _width, TEX_POW, TEX_POW, GS_PSMCT16, 0, 0, 0, 0);
+			_dmaPipe->textureRect(kFullScreen + 0, kFullScreen + 1, _texCoords + 0, _texCoords + 1);
+		} else {
+			_dmaPipe->setTex(_texPtrs[SCREEN], _pitch, TEX_POW, TEX_POW, GS_PSMT8, _clutPtrs[SCREEN], 0, 64, GS_PSMCT32);
+			_dmaPipe->textureRect(_blitCoords + 0, _blitCoords + 1, _texCoords + 0, _texCoords + 1);
+		}
 
-	g_DmacCmd = GS_SET_DISPFB(_frameBufPtr[_curDrawBuf], _tvWidth, GS_PSMCT24); // put it here for dmac/vblank handler
-	_dmaPipe->flush();
-	_curDrawBuf ^= 1;
-	_dmaPipe->setDrawBuffer(_frameBufPtr[_curDrawBuf], _tvWidth, GS_PSMCT24, 0);
+		if (_showMouse) {
+			GsVertex mouseCoords[2];
+			mouseCoords[0].x = (((_mouseX - _hotSpotX) * _mouseScaleX + 8) >> 4) + ORIGIN_X;
+			mouseCoords[0].y = (((_mouseY - _hotSpotY) * _mouseScaleY + 8) >> 4) + ORIGIN_Y;
+			mouseCoords[1].x = mouseCoords[0].x + (((M_SIZE * _mouseScaleX) + 8) >> 4);
+			mouseCoords[1].y = mouseCoords[0].y + (((M_SIZE * _mouseScaleY) + 8) >> 4);
+			mouseCoords[0].z = mouseCoords[1].z = 0;
+
+			_dmaPipe->setTex(_texPtrs[MOUSE], M_SIZE, M_POW, M_POW, GS_PSMT8H, _clutPtrs[MOUSE], 0, 64, GS_PSMCT32);
+			_dmaPipe->textureRect(mouseCoords + 0, mouseCoords + 1, kMouseTex + 0, kMouseTex + 1);
+		}
+
+		_dmaPipe->setTex(_texPtrs[PRINTF], 3 * 128, TEX_POW, TEX_POW, GS_PSMT8H, _clutPtrs[TEXT], 0, 64, GS_PSMCT32);
+		_dmaPipe->textureRect(kFullScreen + 0, kFullScreen + 1, kPrintTex + 0, kPrintTex + 1);
+
+#if 0
+		_ps2sdk_alloc_lock();
+		uint32 heapTop = (uint32)ps2_sbrk(0);
+		_ps2sdk_alloc_unlock();
+		if (heapTop != (uint32)-1) {
+			float yPos = (((float)heapTop) / (32 * 1024 * 1024)) * _tvHeight;
+			GsVertex bottom = { SCALE(_tvWidth - 40) + ORIGIN_X, SCALE(_tvHeight) + ORIGIN_Y, 0 };
+			GsVertex top = { SCALE(_tvWidth) + ORIGIN_X, 0, 0 };
+			top.y = SCALE((uint16)(_tvHeight - yPos)) + ORIGIN_Y;
+			_dmaPipe->flatRect(&bottom, &top, GS_RGBA(0x80, 0, 0, 0x40));
+		}
+#endif
+
+		WaitSema(g_DmacSema);	// wait for dma transfer, if there's one running
+		WaitSema(g_VblankSema); // wait if there's already an image waiting for vblank
+
+		g_DmacCmd = GS_SET_DISPFB(_frameBufPtr[_curDrawBuf], _tvWidth, GS_PSMCT24); // put it here for dmac/vblank handler
+		_dmaPipe->flush();
+		_curDrawBuf ^= 1;
+		_dmaPipe->setDrawBuffer(_frameBufPtr[_curDrawBuf], _tvWidth, GS_PSMCT24, 0);
+	} else
+		_dmaPipe->flush();
 	SignalSema(_screenSema);
 }
 
@@ -384,6 +494,22 @@
 	_blitCoords[1].y = SCALE(_tvHeight + _shakePos) + ORIGIN_Y;
 }
 
+void Gs2dScreen::copyPrintfOverlay(const uint8 *buf) {
+	assert(!((uint32)buf & 63));
+	_dmaPipe->uploadTex(_texPtrs[PRINTF], 3 * 128, 0, 0, GS_PSMT8H, buf, 320, 200);
+	_dmaPipe->flush();
+	_dmaPipe->waitForDma();
+}
+
+void Gs2dScreen::clearPrintfOverlay(void) {
+	uint8 *tmpBuf = (uint8*)memalign(64, 320 * 200);
+	memset(tmpBuf, 4, 320 * 200);
+	_dmaPipe->uploadTex(_texPtrs[PRINTF], 3 * 128, 0, 0, GS_PSMT8H, tmpBuf, 320, 200);
+	_dmaPipe->flush();
+	_dmaPipe->waitForDma();
+	free(tmpBuf);
+}
+
 void Gs2dScreen::copyOverlayRect(const uint16 *buf, uint16 pitch, uint16 x, uint16 y, uint16 w, uint16 h) {
 	WaitSema(g_DmacSema);
 	_overlayChanged = true;
@@ -406,7 +532,7 @@
 		palette[cnt] = ((rgba >> 3) & 0x1F) | (((rgba >> 11) & 0x1F) << 5) | (((rgba >> 19) & 0x1F) << 10);
 	}
 	// now copy the current screen over
-	for (uint32 cnt = 0; cnt < _width * _height; cnt++)
+	for (int cnt = 0; cnt < _width * _height; cnt++)
 		_overlayBuf[cnt] = palette[_screenBuf[cnt]];
 	SignalSema(g_DmacSema);
 }
@@ -453,6 +579,14 @@
 	return _videoMode;
 }
 
+uint16 Gs2dScreen::getWidth(void) {
+	return _width;
+}
+
+uint16 Gs2dScreen::getHeight(void) {
+	return _height;
+}
+
 void Gs2dScreen::wantAnim(bool runIt) {
 	g_RunAnim = runIt;
 }
@@ -475,10 +609,13 @@
 	};
 	float angleStep = ((2 * PI) / _tvHeight);
 
-	while (1) {
+	while (!_systemQuit) {
 		do {
 			WaitSema(g_AnimSema);
-		} while (!g_RunAnim);
+		} while ((!_systemQuit) && (!g_RunAnim));
+		
+		if (_systemQuit)
+			break;
 
 		if (PollSema(_screenSema) > 0) { // make sure no thread is currently drawing
 			WaitSema(g_DmacSema);   // dma transfers have to be finished
@@ -495,6 +632,21 @@
 				_dmaPipe->textureRect(_blitCoords + 0, _blitCoords + 1, _texCoords + 0, _texCoords + 1);
 			}
 
+			_dmaPipe->setTex(_texPtrs[PRINTF], 3 * 128, TEX_POW, TEX_POW, GS_PSMT8H, _clutPtrs[TEXT], 0, 64, GS_PSMCT32);
+			_dmaPipe->textureRect(kFullScreen + 0, kFullScreen + 1, kPrintTex + 0, kPrintTex + 1);
+
+			if (_showMouse) {
+				GsVertex mouseCoords[2];
+				mouseCoords[0].x = (((_mouseX - _hotSpotX) * _mouseScaleX + 8) >> 4) + ORIGIN_X;
+				mouseCoords[0].y = (((_mouseY - _hotSpotY) * _mouseScaleY + 8) >> 4) + ORIGIN_Y;
+				mouseCoords[1].x = mouseCoords[0].x + (((M_SIZE * _mouseScaleX) + 8) >> 4);
+				mouseCoords[1].y = mouseCoords[0].y + (((M_SIZE * _mouseScaleY) + 8) >> 4);
+				mouseCoords[0].z = mouseCoords[1].z = 0;
+
+				_dmaPipe->setTex(_texPtrs[MOUSE], M_SIZE, M_POW, M_POW, GS_PSMT8H, _clutPtrs[MOUSE], 0, 64, GS_PSMCT32);
+				_dmaPipe->textureRect(mouseCoords + 0, mouseCoords + 1, kMouseTex + 0, kMouseTex + 1);
+			}
+
 			_dmaPipe->setAlphaBlend(SOURCE_COLOR, ZERO_COLOR, SOURCE_ALPHA, DEST_COLOR, 0);
 			yPos -= scrlSpeed;
 			if (yPos <= -LINE_SPACE) {
@@ -530,9 +682,9 @@
 
 				uint32 texPtr = _texPtrs[TEXT] + 128 * 16 * 4 * (texIdx >> 1);
 				if (texIdx & 1)
-					_dmaPipe->setTex(_texPtrs[TEXT], 128, 7, 4, GS_PSMT4HL, _clutPtrs[TEXT], 0, 64, GS_PSMCT32);
+					_dmaPipe->setTex(texPtr, 128, 7, 4, GS_PSMT4HL, _clutPtrs[TEXT], 0, 64, GS_PSMCT32);
 				else
-					_dmaPipe->setTex(_texPtrs[TEXT], 128, 7, 4, GS_PSMT4HH, _clutPtrs[TEXT], 0, 64, GS_PSMCT32);
+					_dmaPipe->setTex(texPtr, 128, 7, 4, GS_PSMT4HH, _clutPtrs[TEXT], 0, 64, GS_PSMCT32);
 
 				_dmaPipe->textureRect(nodes + 0, nodes + 1, nodes + 2, nodes + 3,
 					texNodes + 0, texNodes + 1, texNodes + 2, texNodes + 3, GS_RGBA(0x80, 0x80, 0x80, 0x80));
@@ -548,31 +700,13 @@
 			SignalSema(_screenSema);
 		}
 	}
+	ExitThread();
 }
 
 void runAnimThread(Gs2dScreen *param) {
 	param->animThread();
 }
 
-#define ANIM_STACK_SIZE (1024 * 32)
-
-void createAnimThread(Gs2dScreen *screen) {
-	ee_thread_t animThread, thisThread;
-	ReferThreadStatus(GetThreadId(), &thisThread);
-
-	animThread.initial_priority = thisThread.current_priority - 3;
-	animThread.stack = malloc(ANIM_STACK_SIZE);
-	animThread.stack_size = ANIM_STACK_SIZE;
-	animThread.func = (void *)runAnimThread;
-	asm("move %0, $gp\n": "=r"(animThread.gp_reg));
-
-	int tid = CreateThread(&animThread);
-	if (tid >= 0) {
-		StartThread(tid, screen);
-	} else
-		free(animThread.stack);
-}
-
 // data for the animated zeros and ones...
 const uint8 Gs2dScreen::_binaryData[4 * 14 * 2] = {
 	// figure zero
@@ -600,9 +734,12 @@
 	GS_RGBA( 204,  204, 0xFF, 0x40),
 	GS_RGBA( 140,  140, 0xFF, 0x40),
 
-	GS_RGBA(0xFF, 0xFF, 0xFF, 0x80), GS_RGBA(0xFF, 0xFF, 0xFF, 0x80),
-	GS_RGBA(0xFF, 0xFF, 0xFF, 0x80), GS_RGBA(0xFF, 0xFF, 0xFF, 0x80),
-	GS_RGBA(0xFF, 0xFF, 0xFF, 0x80), GS_RGBA(0xFF, 0xFF, 0xFF, 0x80),
+	GS_RGBA(   0,    0,    0, 0x80), // scrPrintf: transparent
+	GS_RGBA(   0,    0,    0, 0x20), // scrPrintf: semitransparent
+	GS_RGBA(0xC0, 0xC0, 0xC0,    0), // scrPrintf: red
+	GS_RGBA(0x16, 0x16, 0xF0,    0), // scrPrintf: blue
+	
+	GS_RGBA(0xFF, 0xFF, 0xFF, 0x80), GS_RGBA(0xFF, 0xFF, 0xFF, 0x80), // unused
 	GS_RGBA(0xFF, 0xFF, 0xFF, 0x80), GS_RGBA(0xFF, 0xFF, 0xFF, 0x80),
 	GS_RGBA(0xFF, 0xFF, 0xFF, 0x80), GS_RGBA(0xFF, 0xFF, 0xFF, 0x80),
 	GS_RGBA(0xFF, 0xFF, 0xFF, 0x80), GS_RGBA(0xFF, 0xFF, 0xFF, 0x80)

Index: Gs2dScreen.h
===================================================================
RCS file: /cvsroot/scummvm/scummvm/backends/ps2/Gs2dScreen.h,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -d -r1.6 -r1.7
--- Gs2dScreen.h	18 Oct 2005 01:30:14 -0000	1.6
+++ Gs2dScreen.h	9 Nov 2005 19:51:57 -0000	1.7
@@ -36,17 +36,29 @@
 	GS_INTERLACED
 };
 
+
+namespace Graphics {
+	struct Surface;
+}
+
 class Gs2dScreen {
 public:
 	Gs2dScreen(uint16 width, uint16 height, TVMode tvMode);
 	~Gs2dScreen(void);
 	void newScreenSize(uint16 width, uint16 height);
 	uint8 tvMode(void);
+	uint16 getWidth(void);
+	uint16 getHeight(void);
 
-	void copyScreenRect(const uint8 *buf, uint16 pitch, uint16 x, uint16 y, uint16 w, uint16 h);
+	void copyPrintfOverlay(const uint8* buf);
+	void clearPrintfOverlay(void);
+	void clearScreen(void);
+
+	void copyScreenRect(const uint8 *buf, int pitch, int x, int y, int w, int h);
 	void setPalette(const uint32 *pal, uint8 start, uint16 num);
-	void grabPalette(uint32 *pal, uint8 start, uint16 num);
 	void updateScreen(void);
+	void grabPalette(uint32 *pal, uint8 start, uint16 num);
+	void grabScreen(Graphics::Surface *surf);
 	//- overlay routines
 	void copyOverlayRect(const uint16 *buf, uint16 pitch, uint16 x, uint16 y, uint16 w, uint16 h);
 	void grabOverlay(uint16 *buf, uint16 pitch);
@@ -61,7 +73,10 @@
 
 	void animThread(void);
 	void wantAnim(bool runIt);
+
+	void quit(void);
 private:
+	void uploadToVram(void);
 	void createAnimTextures(void);
 
 	DmaPipe *_dmaPipe;
@@ -73,7 +88,7 @@
 	uint8  _curDrawBuf;
 	uint32 _frameBufPtr[2]; //
 	uint32 _clutPtrs[3];    //   vram pointers
-	uint32 _texPtrs[3];     //
+	uint32 _texPtrs[4];     //
 
 	uint16 _width, _height, _pitch;
 	int16  _mouseX, _mouseY, _hotSpotX, _hotSpotY;
@@ -88,6 +103,10 @@
 	uint32 *_clut;
 
 	int _screenSema;
+	int _vblankStartId, _vblankEndId, _dmacId, _animTid;
+	void *_animStack;
+	volatile bool _systemQuit;
+
 	static const uint32 _binaryClut[16];
 	static const uint8  _binaryData[4 * 14 * 2];
 	static const uint16 _binaryPattern[16];


Index: asyncfio.cpp
===================================================================
RCS file: /cvsroot/scummvm/scummvm/backends/ps2/asyncfio.cpp,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -d -r1.6 -r1.7
--- asyncfio.cpp	18 Oct 2005 01:30:14 -0000	1.6
+++ asyncfio.cpp	9 Nov 2005 19:51:57 -0000	1.7
@@ -51,6 +51,8 @@
 	fileXioOpen(name, ioMode, DEFAULT_MODE);
 	fileXioWaitAsync(FXIO_WAIT, &res);
 	SignalSema(_ioSema);
+	if (res < -2)
+		printf("File %s error: %d (mode %d)\n", name, res, ioMode);
 	return res;
 }
 
@@ -60,10 +62,8 @@
 	fileXioClose(handle);
 	int res;
 	fileXioWaitAsync(FXIO_WAIT, &res);
-	if (res != 0) {
+	if (res != 0)
 		sioprintf("ERROR: fileXioClose failed, EC %d", res);
-		SleepThread();
-	}
 	_ioSlots[handle] = 0;
 	SignalSema(_ioSema);
 }


Index: fileio.cpp
===================================================================
RCS file: /cvsroot/scummvm/scummvm/backends/ps2/fileio.cpp,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -d -r1.5 -r1.6
--- fileio.cpp	18 Oct 2005 01:30:14 -0000	1.5
+++ fileio.cpp	9 Nov 2005 19:51:57 -0000	1.6
@@ -36,6 +36,8 @@
 #define MAX_CACHED_FILES 6
 #define CACHE_READ_THRESHOLD (16 * 2048)
 #define CACHE_FILL_MIN (2048 * 24)
+#define READ_ALIGN 64	// align all reads to the size of an EE cache line
+#define READ_ALIGN_MASK (READ_ALIGN - 1)
 
 extern void sioprintf(const char *zFormat, ...);
 
@@ -50,7 +52,7 @@
 
 class Ps2ReadFile : public Ps2File {
 public:
-	Ps2ReadFile(int64 cacheId);
+	Ps2ReadFile(int64 cacheId, bool stream);
 	virtual ~Ps2ReadFile(void);
 	virtual bool open(const char *name);
 	virtual uint32 read(void *dest, uint32 len);
@@ -69,9 +71,10 @@
 	uint32 _fileSize, _bytesInCache, _cacheOfs;
 
 	uint32 _readBytesBlock;
+	bool _stream;
 };
 
-Ps2ReadFile::Ps2ReadFile(int64 cacheId) : Ps2File(cacheId) {
+Ps2ReadFile::Ps2ReadFile(int64 cacheId, bool stream) : Ps2File(cacheId) {
 	_fd = -1;
 	_cacheBuf = (uint8*)memalign(64, CACHE_SIZE);
 
@@ -80,6 +83,7 @@
 	_fileSize = _bytesInCache = _cacheOfs = 0;
 	_cacheOpRunning = false;
 	_readBytesBlock = 0;
+	_stream = stream;
 
 	ee_sema_t newSema;
 	newSema.init_count = 1;
@@ -147,7 +151,7 @@
 			seekDest = -1;
 			break;
 	}
-	if ((seekDest >= 0) && (seekDest <= _fileSize)) {
+	if ((seekDest >= 0) && (seekDest <= (int)_fileSize)) {
 		_filePos = seekDest;
 		res = 0;
 	}
@@ -161,7 +165,7 @@
 		if (fio.poll(_fd)) // did it finish?
 			cacheReadSync(); // yes.
 	}
-	if ((!_cacheOpRunning) && (_readBytesBlock >= CACHE_READ_THRESHOLD) && fio.fioAvail()) {
+	if ((!_cacheOpRunning) && ((_readBytesBlock >= CACHE_READ_THRESHOLD) || _stream) && fio.fioAvail()) {
 		// the engine seems to do sequential reads and there are no other I/Os going on. read ahead.
 		uint32 cachePosEnd = _cachePos + _bytesInCache;
 
@@ -176,11 +180,12 @@
 
 		if (_cachePos + _bytesInCache <= _filePos) {
 			_cacheOfs = _bytesInCache = 0;
-			_cachePos = cachePosEnd = _filePos;
+			_cachePos = cachePosEnd = _filePos & ~READ_ALIGN_MASK;
 			assert(_filePos == _physFilePos);
 		} else {
             uint32 cacheDiff = _filePos - _cachePos;
 			assert(_bytesInCache >= cacheDiff);
+			cacheDiff &= ~READ_ALIGN_MASK;
 			_bytesInCache -= cacheDiff;
 			_cachePos += cacheDiff;
 			_cacheOfs = (_cacheOfs + cacheDiff) % CACHE_SIZE;
@@ -188,6 +193,7 @@
 
 		if (_physFilePos != cachePosEnd) {
 			sioprintf("unexpected _physFilePos %d cache %d %d", _physFilePos, _cacheOfs, _bytesInCache);
+			assert(!(cachePosEnd & READ_ALIGN_MASK));
 			_physFilePos = fio.seek(_fd, cachePosEnd, SEEK_SET);
 			if (_physFilePos != cachePosEnd) {
 				sioprintf("cache seek error: seek to %d instead of %d, fs = %d", _physFilePos, cachePosEnd, _fileSize);
@@ -202,7 +208,7 @@
 		if (cacheRead > MAX_READ_STEP)
 			cacheRead = MAX_READ_STEP;
 
-		assert(cacheRead);
+		assert((!(cacheRead & READ_ALIGN_MASK)) && cacheRead);
 
 		_cacheOpRunning = true;
 		fio.read(_fd, _cacheBuf + cacheDest, cacheRead);
@@ -225,7 +231,7 @@
 	if ((_filePos < _cachePos) || (_filePos + len > _cachePos + _bytesInCache))
 		cacheReadSync(); // we have to read from CD, sync cache.
 
-	while (len) {
+	while (len && (_filePos != _fileSize)) {
 		if ((_filePos >= _cachePos) && (_filePos < _cachePos + _bytesInCache)) { // read from cache
 			uint32 staPos = (_cacheOfs + (_filePos - _cachePos)) % CACHE_SIZE;
 			uint32 cpyLen = _bytesInCache - (_filePos - _cachePos);
@@ -246,21 +252,24 @@
 				if ((_filePos < _physFilePos) || (_filePos > _physFilePos + (CACHE_SIZE / 2)))
 					_readBytesBlock = 0; // reset cache hit count
 
-				if (fio.seek(_fd, _filePos, SEEK_SET) == _filePos)
-					_physFilePos = _filePos;
-				else
+				_physFilePos = _filePos & ~READ_ALIGN_MASK;
+				if (fio.seek(_fd, _physFilePos, SEEK_SET) != (int)_physFilePos)
 					break; // read beyond EOF
 			}
-			assert(_physFilePos == _filePos);
-			int doRead = (len > MAX_READ_STEP) ? MAX_READ_STEP : len;
+
+			int doRead = len + (_filePos - _physFilePos);
+			doRead = (doRead + READ_ALIGN_MASK) & ~READ_ALIGN_MASK;
+
+			if (doRead > MAX_READ_STEP)
+				doRead = MAX_READ_STEP;
 			if (doRead < 2048)
 				doRead = 2048;
 
 			fio.read(_fd, _cacheBuf, doRead);
-			_cachePos = _filePos;
+			_cachePos = _physFilePos;
 			_cacheOfs = 0;
 			_bytesInCache = fio.sync(_fd);
-			_physFilePos = _filePos + _bytesInCache;
+			_physFilePos += _bytesInCache;
 			if (!_bytesInCache)
 				break; // EOF
 		}
@@ -303,7 +312,7 @@
 	if ((_fd >= 0) && (_bytesInCache)) {
 		fio.write(_fd, _cacheBuf, _bytesInCache);
 		int wrRes = fio.sync(_fd);
-		if (wrRes != _bytesInCache) // too late to return an error
+		if (wrRes != (int)_bytesInCache) // too late to return an error
 			printf("Cache flush on fclose(): Unable to write %d cached bytes to mc, only %d bytes written\n", _bytesInCache, wrRes);
 	}
 	if (_fd >= 0)
@@ -336,8 +345,7 @@
 
 		if (_bytesInCache == CACHE_SIZE) {
 			fio.write(_fd, _cacheBuf, _bytesInCache);
-			int wrRes = fio.sync(_fd);
-			if (wrRes != _bytesInCache) {
+			if (fio.sync(_fd) != (int)_bytesInCache) {
 				printf("Unable to flush %d cached bytes to memory card!\n", _bytesInCache);
 				return 0;
 			}
@@ -426,17 +434,12 @@
 
 	if (cacheId != 0) {
 		Ps2File *file = findInCache(cacheId);
-		if (file) {
-			//sioprintf("open from cache: %s (%d) [%d]\n", fname, cacheId, file->_handle->_handle);
+		if (file)
 			return (FILE*)file;
-		}
 
 		if (rdOnly) {
-			// smush files need a quite different caching behaviour than normal data files
-			if (strstr(fname, ".san") || strstr(fname, ".SAN") || strstr(fname, ".San"))
-				file = new Ps2SmushFile(cacheId);
-			else
-				file = new Ps2ReadFile(cacheId);
+			bool isAudioFile = strstr(fname, ".bun") || strstr(fname, ".BUN") || strstr(fname, ".Bun");
+			file = new Ps2ReadFile(cacheId, isAudioFile);
 		} else
 			file = new Ps2WriteFile(cacheId);
 
@@ -453,10 +456,17 @@
 	while ((cacheListLen > MAX_CACHED_FILES) || ((openFileCount > 13) && cacheListLen)) {
 		assert(cacheListEnd && cacheListStart);
 		delete cacheListEnd->file;
-		cacheListEnd->prev->next = NULL;
-		FioHandleCache *temp = cacheListEnd;
-		cacheListEnd = cacheListEnd->prev;
-		delete temp;
+		if (cacheListEnd->prev) {
+			cacheListEnd->prev->next = NULL;
+			FioHandleCache *temp = cacheListEnd;
+			cacheListEnd = cacheListEnd->prev;
+			delete temp;
+		} else {
+			assert(cacheListEnd == cacheListStart);
+			assert(cacheListLen == 1);
+			delete cacheListEnd;
+			cacheListEnd = cacheListStart = NULL;
+		}
 		cacheListLen--;
 		openFileCount--;
 	}
@@ -595,7 +605,7 @@
 
 int ps2_fputs(const char *s, FILE *stream) {
 	int len = strlen(s);
-	if (ps2_fwrite(s, 1, len, stream) == len)
+	if (ps2_fwrite(s, 1, len, stream) == (size_t)len)
 		return len;
 	else
 		return EOF;
@@ -657,8 +667,6 @@
 }
 
 int64 TocManager::fileExists(const char *name) {
-	const char *tmpName = name;
-
 	if (((name[_rootLen] != '/') && (name[_rootLen] != '\0')) || (strnicmp(name, _root, _rootLen) != 0)) {
 		for (int i = 0; i < 8; i++)
 			if (name[i] == ':')	// we don't know the content of other drives,



Index: ps2input.cpp
===================================================================
RCS file: /cvsroot/scummvm/scummvm/backends/ps2/ps2input.cpp,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -d -r1.5 -r1.6
--- ps2input.cpp	18 Oct 2005 01:30:14 -0000	1.5
+++ ps2input.cpp	9 Nov 2005 19:51:57 -0000	1.6
@@ -235,11 +235,11 @@
 			entry++;
 			buttonCode >>= 1;
 		}
-		if (_asciiCodes[entry] || _keyCodes[entry]) {
+		if (_padCodes[entry]) {
 			event->type = (down) ? OSystem::EVENT_KEYDOWN : OSystem::EVENT_KEYUP;
-			event->kbd.ascii = _asciiCodes[entry];
-			event->kbd.keycode = _keyCodes[entry];
-			event->kbd.flags = 0;
+			event->kbd.keycode = _padCodes[entry];
+			event->kbd.flags = _padFlags[entry];
+			event->kbd.ascii = mapKey(_padCodes[entry], _padFlags[entry]);
 			return true;
 		}
 	}
@@ -505,41 +505,42 @@
 	/* FF */	0
 };
 
-const int Ps2Input::_keyCodes[16] = {
-	49,	 // '1' - Select
-	0,	 //     - L3
-	0,	 //     - R3
-	286, // F5  - Start
-	0,	 //		- Up
-	0,	 //		- Right
-	0,	 //		- Down
-	0,	 //		- Left
-	0,	 //		- L2
-	0,	 //		- R2
-	0,	 //		- L1
-	0,	 //		- R1
-	27,	 // Esc - Triangle
-	0,	 //		- Circle
-	0,	 //		- Cross
-	0,	 //		- Square
+const int Ps2Input::_padCodes[16] = {
+	SDLK_1,		 // Select
+	0,			 // L3
+	0,			 // R3
+	SDLK_F5,	 // Start
+	0,			 //	Up
+	0,			 //	Right
+	0,			 //	Down
+	0,			 //	Left
+	SDLK_KP0,	 //	L2
+	0,			 //	R2
+	SDLK_n,		 //	L1
+	SDLK_y,		 //	R1
+	SDLK_ESCAPE, // Triangle
+	0,			 //	Circle  => Right mouse button
+	0,			 //	Cross	=> Left mouse button
+	SDLK_RETURN	 //	Square
 };
 
-const uint16 Ps2Input::_asciiCodes[16] = {
-	49,	 // '1' - Select
-	0,	 //     - L3
-	0,	 //     - R3
-	319, // F5  - Start
-	0,	 //		- Up
-	0,	 //		- Right
-	0,	 //		- Down
-	0,	 //		- Left
-	0,	 //		- L2
-	0,	 //		- R2
-	0,	 //		- L1
-	0,	 //		- R1
-	27,	 // Esc - Triangle
-	0,	 //		- Circle
-	0,	 //		- Cross
-	0,	 //		- Square
+const int Ps2Input::_padFlags[16] = {
+	0,			 // Select
+	0,			 // L3
+	0,			 // R3
+	0,			 // Start
+	0,			 //	Up
+	0,			 //	Right
+	0,			 //	Down
+	0,			 //	Left
+	0,			 //	L2
+	0,			 //	R2
+	0,			 //	L1
+	0,			 //	R1
+	0,			 // Triangle
+	0,			 //	Circle
+	0,			 //	Cross
+	0			 //	Square
 };
 
+

Index: ps2input.h
===================================================================
RCS file: /cvsroot/scummvm/scummvm/backends/ps2/ps2input.h,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -d -r1.4 -r1.5
--- ps2input.h	18 Oct 2005 01:30:14 -0000	1.4
+++ ps2input.h	9 Nov 2005 19:51:57 -0000	1.5
@@ -50,8 +50,7 @@
 
 	bool _mouseLoaded, _kbdLoaded;
 	int _keyFlags;
-	static const int _keyCodes[16];
-	static const uint16 _asciiCodes[16];
+	static const int _padCodes[16], _padFlags[16];
 	static const int _usbToSdlk[0x100];
 };
 

Index: ps2pad.cpp
===================================================================
RCS file: /cvsroot/scummvm/scummvm/backends/ps2/ps2pad.cpp,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -d -r1.6 -r1.7
--- ps2pad.cpp	18 Oct 2005 01:30:14 -0000	1.6
+++ ps2pad.cpp	9 Nov 2005 19:51:57 -0000	1.7
@@ -97,6 +97,9 @@
 				case STAT_WAIT_READY:
 					_padStatus = STAT_OKAY;
 					break;
+				case STAT_OKAY:
+					// pad is already initialized
+					break;
 			}
 		} else {
 			// check for timeout...


Index: savefile.cpp
===================================================================
RCS file: /cvsroot/scummvm/scummvm/backends/ps2/savefile.cpp,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -d -r1.7 -r1.8
--- savefile.cpp	18 Oct 2005 01:30:14 -0000	1.7
+++ savefile.cpp	9 Nov 2005 19:51:57 -0000	1.8
@@ -26,33 +26,148 @@
 #include <fileio.h>
 #include <malloc.h>
 #include <ucl/ucl.h>
+#include <libmc.h>
 #include "backends/ps2/savefile.h"
 #include "backends/ps2/Gs2dScreen.h"
-#include "backends/ps2/asyncfio.h"
 #include "backends/ps2/systemps2.h"
 #include "common/scummsys.h"
 
-extern AsyncFio fio;
+#define UCL_MAGIC 0x314C4355
+
+#define PORT 0
+#define SLOT 0
+// port 0, slot 0: memory card in first slot.
+
+void sioprintf(const char *zFormat, ...);
+
+class McAccess {
+public:
+	McAccess(int port, int slot);
+	~McAccess(void);
+	int open(const char *name, int mode);
+	int close(int fd);
+	int size(int fd);
+	int read(int fd, void *buf, int size);
+	int write(int fd, const void *buf, int size);
+	int mkDir(const char *name);
+	int getDir(const char *name, unsigned int mode, int max, void *dest);    
+	int getInfo(int *type, int *free, int *format);
+private:
+	int _sema;
+	int _port, _slot;
+};
+
+McAccess::McAccess(int port, int slot) {
+	_port = port;
+	_slot = slot;
+	ee_sema_t newSema;
+	newSema.init_count = 1;
+	newSema.max_count = 1;
+	_sema = CreateSema(&newSema);
+
+	assert(mcInit(MC_TYPE_MC) >= 0);
+}
+
+McAccess::~McAccess(void) {
+	DeleteSema(_sema);
+}
+
+int McAccess::open(const char *name, int mode) {
+	int res;
+	WaitSema(_sema);
+	mcOpen(_port, _slot, name, mode);
+	mcSync(0, NULL, &res);
+	SignalSema(_sema);
+	return res;
+}
+
+int McAccess::close(int fd) {
+	int res;
+	WaitSema(_sema);
+	mcClose(fd);
+	mcSync(0, NULL, &res);
+	SignalSema(_sema);
+	return res;
+}
+
+int McAccess::size(int fd) {
+	int res, size;
+	WaitSema(_sema);
+	mcSeek(fd, 0, SEEK_END);
+	mcSync(0, NULL, &size);
+	mcSeek(fd, 0, SEEK_SET);
+	mcSync(0, NULL, &res);
+	SignalSema(_sema);
+	assert(res == 0);
+	return size;
+}
+
+int McAccess::read(int fd, void *buf, int size) {
+	int res;
+	WaitSema(_sema);
+	mcRead(fd, buf, size);
+	mcSync(0, NULL, &res);
+	SignalSema(_sema);
+	return res;
+}
+
+int McAccess::write(int fd, const void *buf, int size) {
+	int res;
+	WaitSema(_sema);
+	mcWrite(fd, buf, size);
+	mcSync(0, NULL, &res);
+	SignalSema(_sema);
+	return res;
+}
+
+int McAccess::mkDir(const char *name) {
+	int res;
+	WaitSema(_sema);
+	mcMkDir(_port, _slot, name);
+	mcSync(0, NULL, &res);
+	SignalSema(_sema);
+	return res;
+}
+
+int McAccess::getDir(const char *name, unsigned int mode, int max, void *dest) {
+	int res;
+	WaitSema(_sema);
+	mcGetDir(_port, _slot, name, mode, max, (mcTable*)dest);
+	mcSync(0, NULL, &res);
+	SignalSema(_sema);
+	return res;
+}
+
+int McAccess::getInfo(int *type, int *free, int *format) {
+	int res;
+	WaitSema(_sema);
+	mcGetInfo(_port, _slot, type, free, format);
+	mcSync(0, NULL, &res);
+	SignalSema(_sema);
+	return res;
+}
 
 class UclOutSaveFile : public Common::OutSaveFile {
 public:
-	UclOutSaveFile(const char *filename, Gs2dScreen *screen);
+	UclOutSaveFile(const char *filename, OSystem_PS2 *system, Gs2dScreen *screen, McAccess *mc);
 	virtual ~UclOutSaveFile(void);
 	virtual uint32 write(const void *ptr, uint32 size);
-	virtual int flush(void);
+	virtual void flush(void);
 	virtual bool ioFailed(void);
 	virtual void clearIOFailed(void);
 private:
+	OSystem_PS2 *_system;
 	Gs2dScreen *_screen;
+	McAccess *_mc;
 	int _fd;
 	uint8 *_buf;
 	uint32 _bufSize, _bufPos;
-	bool _ioFailed;
+	bool _ioFailed, _wasFlushed;
 };
 
 class UclInSaveFile : public Common::InSaveFile {
 public:
-	UclInSaveFile(const char *filename, Gs2dScreen *screen);
+	UclInSaveFile(const char *filename, Gs2dScreen *screen, McAccess *mc);
 	virtual ~UclInSaveFile(void);
 	virtual bool eos(void) const;
 	virtual uint32 read(void *ptr, uint32 size);
@@ -61,32 +176,74 @@
 	virtual void skip(uint32 offset);
 private:
 	Gs2dScreen *_screen;
+	McAccess *_mc;
 	uint8 *_buf;
 	uint32 _bufSize, _bufPos;
 	bool _ioFailed;
 };
 
+class AutoSaveFile : public Common::OutSaveFile {
+public:
+	AutoSaveFile(Ps2SaveFileManager *saveMan, const char *filename);
+	~AutoSaveFile(void);
+	virtual uint32 write(const void *ptr, uint32 size);
+	virtual void flush(void) { };
+	virtual bool ioFailed(void) { return false; };
+	virtual void clearIOFailed(void) {};
+private:
+	Ps2SaveFileManager *_saveMan;
+	char _fileName[256];
+	uint8 *_buf;
+	uint32 _bufSize, _bufPos;
+};
+
+AutoSaveFile::AutoSaveFile(Ps2SaveFileManager *saveMan, const char *filename) {
+	strcpy(_fileName, filename);
+	_saveMan = saveMan;
+	_bufSize = 65536;
+	_buf = (uint8*)memalign(64, _bufSize);
+	_bufPos = 0;
+}
+
+AutoSaveFile::~AutoSaveFile(void) {
+	_saveMan->writeSaveNonblocking(_fileName, _buf, _bufPos);
+	free(_buf);
+}
+
+uint32 AutoSaveFile::write(const void *ptr, uint32 size) {
+	uint32 bytesFree = _bufSize - _bufPos;
+	if (bytesFree < size) {
+		uint32 allocBytes = (size > 32 * 1024) ? size : 32 * 1024;
+		_bufSize += allocBytes;
+		_buf = (uint8*)realloc(_buf, _bufSize);
+		bytesFree = _bufSize - _bufPos;
+	}
+	memcpy(_buf + _bufPos, ptr, size);
+	_bufPos += size;
+	return size;
+}
+
 #define MAX_MC_ENTRIES	16
 
+void runSaveThread(Ps2SaveFileManager *param);
+
 Ps2SaveFileManager::Ps2SaveFileManager(OSystem_PS2 *system, Gs2dScreen *screen) {
 	_system = system;
 	_screen = screen;
-	assert(mcInit(MC_TYPE_MC) >= 0);
+	_mc = new McAccess(0, 0);
 
 	_mcDirList = (mcTable*)memalign(64, MAX_MC_ENTRIES * sizeof(mcTable));
 	_mcDirName[0] = '\0';
 	_mcCheckTime = 0;
 	_mcNeedsUpdate = true;
 
-	int mcCheckCount;
-	int res = -10;
 	for (int mcCheckCount = 0; mcCheckCount < 3; mcCheckCount++) {
 		/* retry mcGetInfo 3 times. It slows down startup without mc considerably,
 		   but cheap 3rd party memory cards apparently fail to get detected once in a while */
 
-		int mcType, mcFree, mcFormat, res;
-		mcGetInfo(0, 0, &mcType, &mcFree, &mcFormat);
-		mcSync(0, NULL, &res);
+		int mcType, mcFree, mcFormat;
+		int res = _mc->getInfo(&mcType, &mcFree, &mcFormat);
+
 		if ((res == 0) || (res == -1)) { // mc okay
 			_mcPresent = true;
 			printf("MC okay, result = %d. Type %d, Free %d, Format %d\n", res, mcType, mcFree, mcFormat);
@@ -97,6 +254,29 @@
 			printf("MC failed, not present or not formatted, code %d\n", res);
 		}
 	}
+
+	// create save thread
+	ee_sema_t newSema;
+	newSema.init_count = 0;
+	newSema.max_count = 1;
+	_autoSaveSignal = CreateSema(&newSema);
+	_autoSaveBuf = NULL;
+	_autoSaveSize = 0;
+	_systemQuit = false;
+
+	ee_thread_t saveThread, thisThread;
+	ReferThreadStatus(GetThreadId(), &thisThread);
+
+	saveThread.initial_priority = thisThread.current_priority + 1;
+	saveThread.stack_size = 8 * 1024;
+	_autoSaveStack = malloc(saveThread.stack_size);	
+	saveThread.stack = _autoSaveStack;
+	saveThread.func = (void *)runSaveThread;
+	asm("move %0, $gp\n": "=r"(saveThread.gp_reg));
+
+	_autoSaveTid = CreateThread(&saveThread);
+	assert(_autoSaveTid >= 0);
+	StartThread(_autoSaveTid, this);
 }
 
 Ps2SaveFileManager::~Ps2SaveFileManager(void) {
@@ -104,25 +284,28 @@
 
 void Ps2SaveFileManager::checkMainDirectory(void) {
 	// verify that the main directory (scummvm config + icon) exists
-	int ret;
-	mcGetDir(0, 0, "/ScummVM/*", 0, MAX_MC_ENTRIES, _mcDirList);
-	mcSync(0, NULL, &ret);
+	int ret, fd;
+	_mcNeedsUpdate = true;
+	ret = _mc->getDir("/ScummVM/*", 0, MAX_MC_ENTRIES, _mcDirList);
 	printf("/ScummVM/* res = %d\n", ret);
 	if (ret <= 0) { // assume directory doesn't exist
 		printf("Dir doesn't exist\n");
-		fio.mkdir("mc0:ScummVM");
-		int fd = fio.open("mc0:ScummVM/scummvm.icn", O_WRONLY | O_CREAT | O_TRUNC);
-		if (fd >= 0) {
-			uint16 icoSize;
-			uint16 *icoBuf = decompressIconData(&icoSize);
-			fio.write(fd, icoBuf, icoSize * 2);
-			fio.sync(fd);
-			free(icoBuf);
-			fio.close(fd);
-			printf(".icn written\n");
-			setupIcon("mc0:ScummVM/icon.sys", "scummvm.icn", "ScummVM", "Configuration");
+		ret = _mc->mkDir("/ScummVM");
+		if (ret >= 0) {
+			fd = _mc->open("/ScummVM/scummvm.icn", O_WRONLY | O_CREAT);
+			if (fd >= 0) {
+				uint16 icoSize;
+				uint16 *icoBuf = decompressIconData(&icoSize);
+				ret = _mc->write(fd, icoBuf, icoSize * 2);
+				_mc->close(fd);
+				free(icoBuf);
+
+				printf(".icn written\n");
+				setupIcon("/ScummVM/icon.sys", "scummvm.icn", "ScummVM", "Configuration");
+			} else
+				printf("Can't create icon file: %d\n", fd);
 		} else
-			printf("unable to write icon data\n");
+			printf("can't create scummvm directory: %d\n", ret);
 	}
 }
 
@@ -140,30 +323,31 @@
 }
 
 bool Ps2SaveFileManager::mcReadyForDir(const char *dir) {
-	if (_mcNeedsUpdate || ((_system->getMillis() - _mcCheckTime) > 1000) || !_mcPresent) {
+	if (_mcNeedsUpdate || ((_system->getMillis() - _mcCheckTime) > 2000) || !_mcPresent) {
 		// check if memory card was exchanged/removed in the meantime
 		int mcType, mcFree, mcFormat, mcResult;
-		mcGetInfo(0, 0, &mcType, &mcFree, &mcFormat);
-		mcSync(0, NULL, &mcResult);
+		mcResult = _mc->getInfo(&mcType, &mcFree, &mcFormat);
 		if (mcResult != 0) { // memory card was exchanged
 			_mcNeedsUpdate = true;
-			if (mcResult != -1) {
+			if (mcResult == -1) { // yes, it was exchanged
+				checkMainDirectory(); // make sure ScummVM dir and icon are there
+			} else { // no memorycard in slot or not formatted or something like that
 				_mcPresent = false;
 				printf("MC not found, error code %d\n", mcResult);
 				return false;
 			}
 		}
 		_mcPresent = true;
+		_mcCheckTime = _system->getMillis();
 	}
 	if (_mcNeedsUpdate || strcmp(_mcDirName, dir)) {
 		strcpy(_mcDirName, dir);
 		char dirStr[256];
 		sprintf(dirStr, "/ScummVM-%s/*", dir);
-		mcGetDir(0, 0, dirStr, 0, MAX_MC_ENTRIES, _mcDirList);
-		mcSync(0, NULL, &_mcEntries);
-		return (_mcEntries >= 0);
-	} else
-		return true;
+		_mcEntries = _mc->getDir(dirStr, 0, MAX_MC_ENTRIES, _mcDirList);
+		_mcNeedsUpdate = false;
+	}
+	return (_mcEntries >= 0);
 }
 
 Common::InSaveFile *Ps2SaveFileManager::openForLoading(const char *filename) {
@@ -178,12 +362,12 @@
 				fileExists = true;
 		if (fileExists) {
 			char fullName[256];
-			sprintf(fullName, "mc0:ScummVM-%s/%s", dir, name);
-			UclInSaveFile *file = new UclInSaveFile(fullName, _screen);
+			sprintf(fullName, "/ScummVM-%s/%s", dir, name);
+			UclInSaveFile *file = new UclInSaveFile(fullName, _screen, _mc);
 			if (file) {
-				if (!file->ioFailed()) {
+				if (!file->ioFailed())
 					return file;
-				} else
+				else
 					delete file;
 			}
 		} else
@@ -194,15 +378,17 @@
 }
 
 Common::OutSaveFile *Ps2SaveFileManager::openForSaving(const char *filename) {
-	_screen->wantAnim(true);
+	int res;
 	char dir[256], name[256];
+
+	_screen->wantAnim(true);
 	splitPath(filename, dir, name);
 
 	if (!mcReadyForDir(dir)) {
 		if (_mcPresent) { // directory doesn't seem to exist yet
 			char fullPath[256];
-			sprintf(fullPath, "mc0:ScummVM-%s", dir);
-			fio.mkdir(fullPath);
+			sprintf(fullPath, "/ScummVM-%s", dir);
+			res = _mc->mkDir(fullPath);
 
 			char icoSysDest[256], saveDesc[256];
 			sprintf(icoSysDest, "%s/icon.sys", fullPath);
@@ -215,14 +401,20 @@
 
 	if (_mcPresent) {
 		char fullPath[256];
-		sprintf(fullPath, "mc0:ScummVM-%s/%s", dir, name);
-		UclOutSaveFile *file = new UclOutSaveFile(fullPath, _screen);
-		if (!file->ioFailed()) {
-			// we're creating a file, mc will have to be updated next time
-			_mcNeedsUpdate = true;
+		sprintf(fullPath, "/ScummVM-%s/%s", dir, name);
+		if (strstr(filename, ".s00") || strstr(filename, ".ASD") || strstr(filename, ".asd")) {
+			// this is an autosave
+			AutoSaveFile *file = new AutoSaveFile(this, fullPath);
 			return file;
-		} else
-			delete file;
+		} else {
+			UclOutSaveFile *file = new UclOutSaveFile(fullPath, _system, _screen, _mc);
+			if (!file->ioFailed()) {
+				// we're creating a file, mc will have to be updated next time
+				_mcNeedsUpdate = true;
+				return file;
+			} else
+				delete file;
+		}
 	}
 
 	_screen->wantAnim(false);
@@ -233,8 +425,7 @@
 	_screen->wantAnim(true);
 
 	int mcType, mcFree, mcFormat, mcResult;
-	mcGetInfo(0, 0, &mcType, &mcFree, &mcFormat);
-	mcSync(0, NULL, &mcResult);
+	mcResult = _mc->getInfo(&mcType, &mcFree, &mcFormat);
 
 	memset(marks, false, num * sizeof(bool));
 
@@ -255,9 +446,7 @@
 			ext[0] = '\0';
 		sprintf(mcSearchStr, "/ScummVM-%s/%s*", dirStr, ext);
 
-		int numEntries;
-		mcGetDir(0, 0, mcSearchStr, 0, MAX_MC_ENTRIES, mcEntries);
-		mcSync(0, NULL, &numEntries);
+		int numEntries = _mc->getDir(mcSearchStr, 0, MAX_MC_ENTRIES, mcEntries);
 
 		int searchLen = strlen(ext);
 		for (int i = 0; i < numEntries; i++)
@@ -300,12 +489,12 @@
 	strcpy((char*)icon_sys.copy, ico);
 	strcpy((char*)icon_sys.del, ico);
 
-	int fd = fio.open(dest, O_WRONLY | O_CREAT | O_TRUNC);
+	int fd, res;
+	fd = _mc->open(dest, O_WRONLY | O_CREAT);
 	if (fd >= 0) {
-		fio.write(fd, &icon_sys, sizeof(icon_sys));
-		int res = fio.sync(fd);
-		fio.close(fd);
-		return (res == sizeof(icon_sys));
+		res = _mc->write(fd, &icon_sys, sizeof(icon_sys));
+		_mc->close(fd);
+        return (res == sizeof(icon_sys));
 	} else
 		return false;
 }
@@ -329,25 +518,77 @@
 	return resData;
 }
 
-UclInSaveFile::UclInSaveFile(const char *filename, Gs2dScreen *screen) {
+void runSaveThread(Ps2SaveFileManager *param) {
+	param->saveThread();
+}
+
+void Ps2SaveFileManager::writeSaveNonblocking(char *name, void *buf, uint32 size) {
+	if (buf && size && !_systemQuit) {
+		strcpy(_autoSaveName, name);
+		assert(!_autoSaveBuf);
+		_autoSaveBuf = (uint8*)malloc(size);
+		memcpy(_autoSaveBuf, buf, size);
+		_autoSaveSize = size;
+		SignalSema(_autoSaveSignal);
+	}
+}
+
+void Ps2SaveFileManager::saveThread(void) {
+	while (!_systemQuit) {
+		WaitSema(_autoSaveSignal);
+		if (_autoSaveBuf && _autoSaveSize) {
+			UclOutSaveFile *outSave = new UclOutSaveFile(_autoSaveName, _system, _screen, _mc);
+			if (!outSave->ioFailed()) {
+				outSave->write(_autoSaveBuf, _autoSaveSize);
+				outSave->flush();
+			}
+			if (outSave->ioFailed())
+				_system->msgPrintf(5000, "Writing autosave to %s failed", _autoSaveName);
+			delete outSave;
+			free(_autoSaveBuf);
+			_autoSaveBuf = NULL;
+			_autoSaveSize = 0;
+			_mcNeedsUpdate = true; // we've created a file, mc will have to be updated
+			_screen->wantAnim(false);
+		}
+	}
+	ExitThread();
+}
+
+void Ps2SaveFileManager::quit(void) {
+	_systemQuit = true;
+	ee_thread_t statSave, statThis;
+	ReferThreadStatus(GetThreadId(), &statThis);
+	int res = ChangeThreadPriority(_autoSaveTid, statThis.current_priority - 1);
+	sioprintf("SaveThread prio res: %d", res);
+
+	do {	// wait until thread called ExitThread()
+		SignalSema(_autoSaveSignal);
+		ReferThreadStatus(_autoSaveTid, &statSave);
+	} while (statSave.status != 0x10);
+	sioprintf("wait done");
+	DeleteThread(_autoSaveTid);
+    free(_autoSaveStack);
+}
+
+UclInSaveFile::UclInSaveFile(const char *filename, Gs2dScreen *screen, McAccess *mc) {
 	_screen = screen;
-	int fd = fio.open(filename, O_RDONLY);
+	_mc = mc;
+	int fd = _mc->open(filename, O_RDONLY);
 	_buf = NULL;
 	_bufSize = _bufPos = 0;
 	_ioFailed = false;
 
 	if (fd >= 0) {
-		int srcSize = fio.seek(fd, 0, SEEK_END);
-		fio.seek(fd, 0, SEEK_SET);
-		if (srcSize > 4) {
+		int srcSize = _mc->size(fd);
+		if (srcSize > 8) {
 			int res;
-			uint8 *tmpBuf = (uint8*)malloc(srcSize);
-			fio.read(fd, tmpBuf, srcSize);
-			res = fio.sync(fd);
-			if (res == srcSize) {
-				uint32 resLen = _bufSize = *(uint32*)tmpBuf;
+			uint8 *tmpBuf = (uint8*)memalign(64, srcSize);
+			res = _mc->read(fd, tmpBuf, srcSize);
+			if ((res == srcSize) && (*(uint32*)tmpBuf == UCL_MAGIC)) {
+				uint32 resLen = _bufSize = *(uint32*)(tmpBuf + 4);
 				_buf = (uint8*)malloc(_bufSize + 2048);
-				res = ucl_nrv2e_decompress_8(tmpBuf + 4, srcSize - 4, _buf, &resLen, NULL);
+				res = ucl_nrv2e_decompress_8(tmpBuf + 8, srcSize - 8, _buf, &resLen, NULL);
 				if ((res < 0) || (resLen != _bufSize)) {
 					printf("Unable to decompress file %s (%d -> %d) error code %d\n", filename, srcSize, _bufSize, res);
 					free(_buf);
@@ -357,11 +598,11 @@
 			}
 			free(tmpBuf);
 		}
-		if (!_buf) {
-			printf("Invalid savegame %s\n", filename);
-			_ioFailed = true;
-		}
-		fio.close(fd);
+		_mc->close(fd);
+	}
+	if (!_buf) {
+		printf("Invalid savegame %s\n", filename);
+		_ioFailed = true;
 	}
 }
 
@@ -384,27 +625,36 @@
 }
 
 uint32 UclInSaveFile::read(void *ptr, uint32 size) {
-	uint32 bytesRemain = _bufSize - _bufPos;
-	if (size > bytesRemain) {
-		size = bytesRemain;
+	if (_buf) {
+		uint32 bytesRemain = _bufSize - _bufPos;
+		if (size > bytesRemain) {
+			size = bytesRemain;
+			_ioFailed = true;
+		}
+		memcpy(ptr, _buf + _bufPos, size);
+		_bufPos += size;
+		return size;
+	} else {
 		_ioFailed = true;
+		return 0;
 	}
-	memcpy(ptr, _buf + _bufPos, size);
-	_bufPos += size;
-	return size;
 }
 
 void UclInSaveFile::skip(uint32 offset) {
-	if (_bufPos + offset <= _bufSize)
-		_bufPos += offset;
-	else
-		_bufPos = _bufSize;
+	if (_buf) {
+		if (_bufPos + offset <= _bufSize)
+			_bufPos += offset;
+		else
+			_bufPos = _bufSize;
+	}
 }
 
-UclOutSaveFile::UclOutSaveFile(const char *filename, Gs2dScreen *screen) {
+UclOutSaveFile::UclOutSaveFile(const char *filename, OSystem_PS2 *system, Gs2dScreen *screen, McAccess *mc) {
 	_screen = screen;
+	_system = system;
+	_mc = mc;
 	_bufPos = 0;
-	_fd = fio.open(filename, O_WRONLY | O_CREAT | O_TRUNC);
+	_fd = _mc->open(filename, O_WRONLY | O_CREAT);
 	if (_fd >= 0) {
 		_bufSize = 65536;
 		_buf = (uint8*)malloc(_bufSize);
@@ -414,16 +664,24 @@
 		_bufSize = 0;
 		_buf = NULL;
 	}
+	_wasFlushed = false;
 }
 
 UclOutSaveFile::~UclOutSaveFile(void) {
 	if (_buf) {
-		if (flush() < 0)
-			printf("~UclOutSaveFile: Flush failed!\n");
+		if (_bufPos) {
+			printf("Engine didn't call SaveFile::flush()\n");
+			flush();
+			if (ioFailed()) {
+				// unable to save to memory card and it's too late to return an error code to the engine
+				_system->msgPrintf(5000, "!WARNING!\nCan't write to memory card.\nGame was NOT saved.");
+				printf("~UclOutSaveFile: Flush failed!\n");
+			}
+		}
 		free(_buf);
 	}
 	if (_fd >= 0)
-		fio.close(_fd);
+		_mc->close(_fd);
 	_screen->wantAnim(false);
 }
 
@@ -435,33 +693,36 @@
 	_ioFailed = false;
 }
 
-int UclOutSaveFile::flush(void) {
-	if (_bufPos == 0)
-		return 0; // no data to flush
-	if (_buf) {
-		uint8 *compBuf = (uint8*)malloc(_bufPos * 2);
-		uint32 compSize = _bufPos * 2;
-		int res = ucl_nrv2e_99_compress(_buf, _bufPos, compBuf, &compSize, NULL, 10, NULL, NULL);
-		if (res >= 0) {
-			fio.write(_fd, &_bufPos, 4);
-			if (fio.sync(_fd) == 4) {
-				fio.write(_fd, compBuf, compSize);
-				if (fio.sync(_fd) != compSize)
+void UclOutSaveFile::flush(void) {
+	int res = 0;
+
+	if (_bufPos) {
+		if (_wasFlushed) {
+			// the engine flushed this file and afterwards wrote more data.
+			// this is unsupported because it results in savefiles that consist
+			// of two or more compressed segments.
+			printf("Error: 2nd call to UclOutSaveFile::flush!\n");
+			res = -1;
+		} else {
+			uint32 compSize = _bufPos * 2;
+			uint8 *compBuf = (uint8*)memalign(64, compSize + 8);
+			*(uint32*)(compBuf + 0) = UCL_MAGIC;
+			*(uint32*)(compBuf + 4) = _bufPos; // uncompressed size
+			res = ucl_nrv2e_99_compress(_buf, _bufPos, compBuf + 8, &compSize, NULL, 10, NULL, NULL);
+			if (res >= 0) {
+				res = _mc->write(_fd, compBuf, compSize + 8);
+				if (res != (int)compSize + 8)
 					res = -1;
 			} else
-				res = -1;
-		} else
-			printf("Unable to compress %d bytes of savedata, errorcode %d\n", _bufPos, res);
-		free(compBuf);
-
-		if (res >= 0) {
+				printf("Unable to compress %d bytes of savedata, errorcode %d\n", _bufPos, res);
+			free(compBuf);
 			_bufPos = 0;
-			return 0;
 		}
 	}
-	_ioFailed = true;
-	printf("UclOutSaveFile::flush failed!\n");
-	return -1;
+	if (res < 0) {
+		_ioFailed = true;
+		printf("UclOutSaveFile::flush failed!\n");
+	}
 }
 
 uint32 UclOutSaveFile::write(const void *ptr, uint32 size) {

Index: savefile.h
===================================================================
RCS file: /cvsroot/scummvm/scummvm/backends/ps2/savefile.h,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -d -r1.6 -r1.7
--- savefile.h	18 Oct 2005 01:30:14 -0000	1.6
+++ savefile.h	9 Nov 2005 19:51:57 -0000	1.7
@@ -22,17 +22,12 @@
 #ifndef __PS2_SAVEFILE__
 #define __PS2_SAVEFILE__
 
-#include "common/savefile.h"
 #include <libmc.h>
-
-enum SaveMode {
-	TO_HOST = 0,
-	TO_MC,
-	TO_HDD
-};
+#include "common/savefile.h"
 
 class Gs2dScreen;
 class OSystem_PS2;
+class McAccess;
 
 class Ps2SaveFileManager : public Common::SaveFileManager {
 public:
@@ -45,8 +40,12 @@
 
 	/** Get the path to the save game directory. */
 	virtual const char *getSavePath() const;
+
+	void writeSaveNonblocking(char *name, void *buf, uint32 size);
+	void saveThread(void);
+	void quit(void);
 private:
-	static bool setupIcon(const char *dest, const char *ico, const char *descr1, const char *descr2);
+	bool setupIcon(const char *dest, const char *ico, const char *descr1, const char *descr2);
 
 	bool mcReadyForDir(const char *dir);
 
@@ -56,6 +55,15 @@
 
 	Gs2dScreen *_screen;
 	OSystem_PS2 *_system;
+	McAccess	*_mc;
+
+	int _autoSaveTid;
+	int _autoSaveSignal;
+	void *_autoSaveStack;
+	volatile bool _systemQuit;
+	uint8 *_autoSaveBuf;
+	uint32 _autoSaveSize;
+	char _autoSaveName[256];
 
 	mcTable *_mcDirList;
 	int		_mcEntries;


Index: systemps2.cpp
===================================================================
RCS file: /cvsroot/scummvm/scummvm/backends/ps2/systemps2.cpp,v
retrieving revision 1.9
retrieving revision 1.10
diff -u -d -r1.9 -r1.10
--- systemps2.cpp	18 Oct 2005 01:30:14 -0000	1.9
+++ systemps2.cpp	9 Nov 2005 19:51:57 -0000	1.10
@@ -43,6 +43,7 @@
 #include "common/file.h"
 #include "backends/ps2/sysdefs.h"
 #include <libmc.h>
+#include <libpad.h>
 #include "backends/ps2/cd.h"
 #include <sio.h>
 #include <fileXio_rpc.h>
@@ -53,8 +54,8 @@
 #define SOUND_STACK_SIZE (1024 * 32)
 #define SMP_PER_BLOCK 800
 #define FROM_BCD(a) ((a >> 4) * 10 + (a & 0xF))
-#define BUS_CLOCK (150 * 1000 * 1000) // 150 Mhz Bus clock
-#define CLK_DIVIS 5859	// the timer IRQ handler gets called (BUS_CLOCK / 256) / CLK_DIVIS times per second (~100 times)
+#define BUS_CLOCK 147456000 // bus clock, a little less than 150 mhz
+#define CLK_DIVIS 5760	// the timer IRQ handler gets called (BUS_CLOCK / 256) / CLK_DIVIS times per second (100 times)
 
 #ifdef USE_PS2LINK
 #define IRX_PREFIX "host:"
@@ -67,14 +68,14 @@
 static int g_TimerThreadSema = -1, g_SoundThreadSema = -1;
 static int g_MainWaitSema = -1, g_TimerWaitSema = -1;
 static volatile int32 g_MainWakeUp = 0, g_TimerWakeUp = 0;
-static volatile uint64 msecCount = 0;
+static volatile uint32 msecCount = 0;
 
 OSystem_PS2 *g_systemPs2 = NULL;
 
-void readRtcTime(void);
-
 int gBitFormat = 555;
 
+#define FOREVER 2147483647
+
 namespace Graphics {
 	extern const NewFont g_sysfont;
 };
@@ -84,7 +85,7 @@
 	char resStr[2048];
 
 	va_start(ap,zFormat);
-	int res = vsnprintf(resStr, 2048, zFormat, ap);
+	vsnprintf(resStr, 2048, zFormat, ap);
 	va_end(ap);
 
 	sio_puts(resStr);
@@ -113,7 +114,7 @@
 	sio_puts("IOP synced.");
 	SifInitRpc(0);
 	SifLoadFileInit();
-    cdvdInit(CDVD_INIT_NOWAIT);
+	cdvdInit(CDVD_INIT_NOWAIT);
 #endif
 
 	ee_thread_t thisThread;
@@ -143,8 +144,8 @@
 }
 
 s32 timerInterruptHandler(s32 cause) {
-	msecCount += (((uint64)256 * CLK_DIVIS) << 32) / (BUS_CLOCK / 1000);
 	T0_MODE = 0xDC2; // same value as in initialization.
+	msecCount += 10;
 
 	iSignalSema(g_SoundThreadSema);
 	iSignalSema(g_TimerThreadSema);
@@ -175,54 +176,66 @@
 }
 
 OSystem_PS2::OSystem_PS2(void) {
-	sioprintf("OSystem_PS2 constructor\n");
-
 	_soundStack = _timerStack = NULL;
 	_scummTimerProc = NULL;
 	_scummSoundProc = NULL;
 	_scummSoundParam = NULL;
+	_printY = 0;
+	_msgClearTime = 0;
+	_systemQuit = false;
 
 	_screen = new Gs2dScreen(320, 200, TV_DONT_CARE);
-	_width = 320;
-	_height = 200;
 
-	sioprintf("Initializing timer\n");
+	sioprintf("Initializing system...");
 	initTimer();
 
 	_screen->wantAnim(true);
 
-	char errorStr[256];
-	if (!loadModules(errorStr))
-		fatalError(errorStr);
+	sioprintf("Loading IOP modules...");
+	loadModules();
 
-	sioprintf("Initializing SjPCM");
-	if (SjPCM_Init(0) < 0)
-		fatalError("SjPCM Bind failed");
+	int res;
+	if ((res = SjPCM_Init(0)) < 0) {
+		msgPrintf(FOREVER, "SjPCM Bind failed: %d", res);
+		quit();
+	}
 
-	if (CDVD_Init() != 0)
-		fatalError("CDVD_Init failed");
+	if ((res = CDVD_Init()) != 0) {
+		msgPrintf(FOREVER, "CDVD Init failed: %d", res);
+		quit();
+	}
+	
+	if ((res = fileXioInit()) < 0) {
+		msgPrintf(FOREVER, "FXIO Init failed: %d", res);
+		quit();
+	}
+	fileXioSetBlockMode(FXIO_NOWAIT);
 
 	_mouseVisible = false;
 
 	sioprintf("reading RTC");
 	readRtcTime();
 
-	sioprintf("Initializing FXIO");
-	if (fileXioInit() < 0)
-		fatalError("Can't init fileXio");
-
-	fileXioSetBlockMode(FXIO_NOWAIT);
-
 	sioprintf("Starting SavefileManager");
 	_saveManager = new Ps2SaveFileManager(this, _screen);
 
-	_soundBufL = (int16*)malloc(SMP_PER_BLOCK * sizeof(int16));
-	_soundBufR = (int16*)malloc(SMP_PER_BLOCK * sizeof(int16));
-
 	sioprintf("Initializing ps2Input");
 	_input = new Ps2Input(this, _useMouse, _useKbd);
 
+#ifdef _REC_MUTEX_
+	_mutex = new Ps2Mutex[MAX_MUTEXES];
+
+	ee_sema_t newSema;
+	newSema.init_count = 1;
+	newSema.max_count = 1;
+	_mutexSema = CreateSema(&newSema);
+	for (int i = 0; i < MAX_MUTEXES; i++) {
+		_mutex[i].sema = -1;
+		_mutex[i].count = _mutex[i].owner = 0;
+	}
+#endif
 	_screen->wantAnim(false);
+	_screen->clearScreen();
 }
 
 OSystem_PS2::~OSystem_PS2(void) {
@@ -267,7 +280,7 @@
 	StartThread(_timerTid, this);
 	StartThread(_soundTid, this);
 
-	// these semaphores are used for OSystem::delay()
+	// these semaphores are used for OSystem::delayMillis()
 	threadSema.init_count = 0;
 	threadSema.max_count = 1;
 	g_MainWaitSema = CreateSema(&threadSema);
@@ -275,20 +288,22 @@
 	assert((g_MainWaitSema >= 0) && (g_TimerWaitSema >= 0));
 
 	// threads done, start the interrupt handler
-	AddIntcHandler( INT_TIMER0, timerInterruptHandler, 0); // 0=first handler
+	_intrId = AddIntcHandler( INT_TIMER0, timerInterruptHandler, 0); // 0=first handler
+	assert(_intrId >= 0);
 	EnableIntc(INT_TIMER0);
 	T0_HOLD = 0;
 	T0_COUNT = 0;
-	T0_COMP = CLK_DIVIS; // (busclock / 256) / 5859 = ~ 100.0064
+	T0_COMP = CLK_DIVIS; // (BUS_CLOCK / 256) / CLK_DIVIS = 100
 	T0_MODE = TIMER_MODE( 2, 0, 0, 0, 1, 1, 1, 0, 1, 1);
 }
 
 void OSystem_PS2::timerThread(void) {
-	while (1) {
+	while (!_systemQuit) {
 		WaitSema(g_TimerThreadSema);
 		if (_scummTimerProc)
 			_scummTimerProc(0);
 	}
+	ExitThread();
 }
 
 void OSystem_PS2::soundThread(void) {
@@ -298,9 +313,12 @@
 	_soundSema = CreateSema(&soundSema);
 	assert(_soundSema >= 0);
 
+	int16 *soundBufL = (int16*)memalign(64, SMP_PER_BLOCK * sizeof(int16) * 2);
+	int16 *soundBufR = soundBufL + SMP_PER_BLOCK;
+
 	int bufferedSamples = 0;
 	int cycles = 0;
-	while (1) {
+	while (!_systemQuit) {
 		WaitSema(g_SoundThreadSema);
 
 		if (!(cycles & 31))
@@ -311,7 +329,7 @@
 
 		WaitSema(_soundSema);
 		if (_scummSoundProc) {
-			if (bufferedSamples <= 8 * SMP_PER_BLOCK) {
+			if (bufferedSamples <= 4 * SMP_PER_BLOCK) {
 				// we have to produce more samples, call sound mixer
 				// the scratchpad at 0x70000000 is used as temporary soundbuffer
 				_scummSoundProc(_scummSoundParam, (uint8*)0x70000000, SMP_PER_BLOCK * 2 * sizeof(int16));
@@ -343,20 +361,25 @@
 					"  addiu $t8, 32\n\t"
 					"  bnez  $t9, loop\n\t"		// loop
 						:  // outputs
-				 		: "r"(_soundBufL), "r"(_soundBufR)  // inputs
+				 		: "r"(soundBufL), "r"(soundBufR)  // inputs
 					//  : "$t2", "$t3", "$t4", "$t5", "$t6", "$t7", "$t8", "$t9"  // destroyed
 						: "$10", "$11", "$12", "$13", "$14", "$15", "$24", "$25"  // destroyed
 				);
 				// and feed it into the SPU
-				SjPCM_Enqueue((short int*)_soundBufL, (short int*)_soundBufR, SMP_PER_BLOCK, 0);
+				// non-blocking call, the function will return before the buffer's content
+				// was transferred.
+				SjPCM_Enqueue((short int*)soundBufL, (short int*)soundBufR, SMP_PER_BLOCK, 0);
 				bufferedSamples += SMP_PER_BLOCK;
 			}
 		}
 		SignalSema(_soundSema);
 	}
+	free(soundBufL);
+	DeleteSema(_soundSema);
+	ExitThread();
 }
 
-char *irxModules[] = {
+const char *irxModules[] = {
 	"rom0:SIO2MAN",
 	"rom0:MCMAN",
 	"rom0:MCSERV",
@@ -370,40 +393,37 @@
 	IRX_PREFIX "SJPCM.IRX" IRX_SUFFIX
 };
 
-bool OSystem_PS2::loadModules(char *errorStr) {
+void OSystem_PS2::loadModules(void) {
 
-	_useHdd = _useMouse = _useKbd = false;
+	_useMouse = _useKbd = false;
 
 	int res;
 	for (int i = 0; i < ARRAYSIZE(irxModules); i++) {
 		if ((res = SifLoadModule(irxModules[i], 0, NULL)) < 0) {
-			sprintf(errorStr, "Can't load module %s (%d)", irxModules[i], res);
-			return false;
+			msgPrintf(FOREVER, "Unable to load module %s, Error %d", irxModules[i], res);
+			_screen->wantAnim(false);
+			updateScreen();
+			SleepThread();
 		}
 	}
-	printf("Modules loaded\n");
+
 	// now try to load optional IRXs
-	if ((res = SifLoadModule(IRX_PREFIX "USBD.IRX" IRX_SUFFIX, 0, NULL)) < 0)
-		sioprintf("Cannot load module: USBD.IRX (%d)\n", res);
-	else {
+	if ((res = SifLoadModule(IRX_PREFIX "USBD.IRX" IRX_SUFFIX, 0, NULL)) >= 0) {
 		if ((res = SifLoadModule(IRX_PREFIX "PS2MOUSE.IRX" IRX_SUFFIX, 0, NULL)) < 0)
-			sioprintf("Cannot load module: PS2MOUSE.IRX (%d)\n", res);
+			sioprintf("Cannot load module: PS2MOUSE.IRX (%d)", res);
 		else
 			_useMouse = true;
 		if ((res = SifLoadModule(IRX_PREFIX "RPCKBD.IRX" IRX_SUFFIX, 0, NULL)) < 0)
-			sioprintf("Cannot load module: RPCKBD.IRX (%d)\n", res);
+			sioprintf("Cannot load module: RPCKBD.IRX (%d)", res);
 		else
 			_useKbd = true;
 	}
-	sioprintf("Modules: UsbMouse %sloaded, UsbKbd %sloaded, Hdd %sloaded.", _useMouse ? "" : "not ", _useKbd ? "" : "not ", _useHdd ? "" : "not ");
-	return true;
+	sioprintf("Modules: UsbMouse %sloaded, UsbKbd %sloaded.", _useMouse ? "" : "not ", _useKbd ? "" : "not ");
 }
 
 void OSystem_PS2::initSize(uint width, uint height, int overscale) {
 	printf("initializing new size: (%d/%d)...", width, height);
 	_screen->newScreenSize(width, height);
-	_width = width;
-	_height = height;
 	_screen->setMouseXy(width / 2, height / 2);
 	_input->newRange(0, 0, width - 1, height - 1);
 	_input->warpTo(width / 2, height / 2);
@@ -422,30 +442,24 @@
 }
 
 void OSystem_PS2::copyRectToScreen(const byte *buf, int pitch, int x, int y, int w, int h) {
-	if (x < 0) {
-		w += x;
-		buf -= x;
-		x = 0;
-	}
-	if (y < 0) {
-		h += y;
-		buf -= y * pitch;
-		y = 0;
-	}
-	if (x + w > _width)
-		w = _width - x;
-	if (y + h > _height)
-		h = _height - y;
-	if ((w > 0) && (h > 0))
-		_screen->copyScreenRect((const uint8*)buf, (uint16)pitch, (uint16)x, (uint16)y, (uint16)w, (uint16)h);
+	_screen->copyScreenRect((const uint8*)buf, pitch, x, y, w, h);
+}
+
+bool OSystem_PS2::grabRawScreen(Graphics::Surface *surf) {
+	_screen->grabScreen(surf);
+	return true;
 }
 
 void OSystem_PS2::updateScreen(void) {
+	if (_msgClearTime && (_msgClearTime < getMillis())) {
+		_screen->clearPrintfOverlay();
+		_msgClearTime = 0;
+	}
 	_screen->updateScreen();
 }
 
 uint32 OSystem_PS2::getMillis(void) {
-	return (uint32)(msecCount >> 32);
+	return msecCount;
 }
 
 void OSystem_PS2::delayMillis(uint msecs) {
@@ -500,6 +514,7 @@
 	return _saveManager;
 }
 
+#ifndef _REC_MUTEX_
 OSystem::MutexRef OSystem_PS2::createMutex(void) {
 	ee_sema_t newSema;
 	newSema.init_count = 1;
@@ -521,6 +536,68 @@
 void OSystem_PS2::deleteMutex(MutexRef mutex) {
 	DeleteSema((int)mutex);
 }
+#else
+OSystem::MutexRef OSystem_PS2::createMutex(void) {
+	WaitSema(_mutexSema);
+	Ps2Mutex *mutex = NULL;
+	for (int i = 0; i < MAX_MUTEXES; i++)
+		if (_mutex[i].sema < 0) {
+			mutex = _mutex + i;
+			break;
+		}
+	if (mutex) {
+		ee_sema_t newSema;
+		newSema.init_count = 1;
+		newSema.max_count = 1;
+		mutex->sema = CreateSema(&newSema);
+		mutex->owner = mutex->count = 0;
+	} else
+		printf("OSystem_PS2::createMutex: ran out of Mutex slots!\n");
+	SignalSema(_mutexSema);
+	return (OSystem::MutexRef)mutex;
+}
+
+void OSystem_PS2::lockMutex(MutexRef mutex) {
+	WaitSema(_mutexSema);
+	Ps2Mutex *sysMutex = (Ps2Mutex*)mutex;
+	int tid = GetThreadId();
+	assert(tid != 0);
+	if (sysMutex->owner && (sysMutex->owner == tid))
+		sysMutex->count++;
+	else {
+		SignalSema(_mutexSema);
+		WaitSema(sysMutex->sema);
+		WaitSema(_mutexSema);
+		sysMutex->owner = tid;
+		sysMutex->count = 0;
+	}
+	SignalSema(_mutexSema);
+}
+
+void OSystem_PS2::unlockMutex(MutexRef mutex) {
+	WaitSema(_mutexSema);
+	Ps2Mutex *sysMutex = (Ps2Mutex*)mutex;
+	int tid = GetThreadId();
+	if (sysMutex->owner && sysMutex->count && (sysMutex->owner == tid))
+		sysMutex->count--;
+	else {
+		assert(sysMutex->count == 0);
+		SignalSema(sysMutex->sema);
+		sysMutex->owner = 0;
+	}
+	SignalSema(_mutexSema);
+}
+
+void OSystem_PS2::deleteMutex(MutexRef mutex) {
+	WaitSema(_mutexSema);
+	Ps2Mutex *sysMutex = (Ps2Mutex*)mutex;
+	if (sysMutex->owner || sysMutex->count)
+		printf("WARNING: Deleting LOCKED mutex!\n");
+	DeleteSema(sysMutex->sema);
+	sysMutex->sema = -1;
+	SignalSema(_mutexSema);
+}
+#endif
 
 void OSystem_PS2::setShakePos(int shakeOffset) {
 	_screen->setShakePos(shakeOffset);
@@ -615,40 +692,90 @@
 }
 
 int16 OSystem_PS2::getHeight(void) {
-	return _height;
+	return _screen->getHeight();
 }
 
 int16 OSystem_PS2::getWidth(void) {
-	return _width;
+	return _screen->getWidth();
 }
 
-void OSystem_PS2::quit(void) {
-	printf("OSystem_PS2::quit\n");
-	clearSoundCallback();
-	setTimerCallback(NULL, 0);
-	SleepThread();
-}
+void OSystem_PS2::msgPrintf(int millis, char *format, ...) {
+	va_list ap;
+	char resStr[1024];
+	memset(resStr, 0, 1024);
+
+	va_start(ap, format);
+	vsnprintf(resStr, 1023, format, ap);
+	va_end(ap);
+
+	uint16 posY = 2;
+	int maxWidth = 0;
 
-void OSystem_PS2::fatalError(char *errorStr) {
-	sioprintf("ERROR: %s", errorStr);
-	printf("ERROR: %s\n", errorStr);
 	Graphics::Surface surf;
 	surf.create(300, 200, 1);
-	Common::String str(errorStr);
-	Graphics::g_sysfont.drawString(&surf, str, 0, 0, 300, 0xFF);
 
-	uint32 palette[256];
-	palette[0] = 0x00400000;
-	for (int i = 1; i < 256; i++)
-		palette[i] = 0xFFFFFFFF;
+	char *lnSta = resStr;
+	while (*lnSta && (posY < 180)) {
+		char *lnEnd = lnSta;
+		while ((*lnEnd) && (*lnEnd != '\n'))
+			lnEnd++;
+		*lnEnd = '\0';
+		
+		Common::String str(lnSta);
+		int width = Graphics::g_sysfont.getStringWidth(str);
+		if (width > maxWidth)
+			maxWidth = width;
+		int posX = (300 - width) / 2;
+		Graphics::g_sysfont.drawString(&surf, str, posX, posY, 300 - posX, 1);
+		posY += 14;
 
-	_screen->setPalette(palette, 0, 256);
-	_screen->hideOverlay();
+        lnSta = lnEnd + 1;
+	}
+
+	uint8 *scrBuf = (uint8*)memalign(64, 320 * 200);
+	memset(scrBuf, 4, 320 * 200);
+
+	uint8 *dstPos = scrBuf + ((200 - posY) >> 1) * 320 + (320 - maxWidth) / 2;
+	for (int y = 0; y < posY; y++) {
+		uint8 *srcPos = (uint8*)surf.getBasePtr((300 - maxWidth) / 2, y);
+		for (int x = 0; x < maxWidth; x++)
+			dstPos[x] = srcPos[x] + 5;
+		dstPos += 320;
+	}
+	surf.free();
+	_screen->copyPrintfOverlay(scrBuf);
+	free(scrBuf);
+	_msgClearTime = millis + getMillis();
+}
+
+void OSystem_PS2::quit(void) {
+	sioprintf("OSystem_PS2::quit");
+	clearSoundCallback();
+	setTimerCallback(NULL, 0);
 	_screen->wantAnim(false);
+	_systemQuit = true;
+	ee_thread_t statSound, statTimer;
+	do {	// wait until both threads called ExitThread()
+		ReferThreadStatus(_timerTid, &statTimer);
+		ReferThreadStatus(_soundTid, &statSound);
+	} while ((statSound.status != 0x10) || (statTimer.status != 0x10));
+	DeleteThread(_timerTid);
+	DeleteThread(_soundTid);
+	free(_timerStack);
+	free(_soundStack);
+	DisableIntc(INT_TIMER0);
+	RemoveIntcHandler(INT_TIMER0, _intrId);
 
-	_screen->copyScreenRect((uint8*)surf.getBasePtr(0, 0), surf.pitch, 10, 10, 300, 100);
-	_screen->updateScreen();
-	SleepThread();
+	_saveManager->quit();
+	_screen->quit();
+
+	padEnd(); // stop pad library
+	cdvdInit(CDVD_EXIT);
+	cdvdExit();
+	SifExitIopHeap();
+	SifLoadFileExit();
+	SifExitRpc();
+	LoadExecPS2("cdrom0:\\SCUMMVM.ELF", 0, NULL); // resets the console and executes the ELF
 }
 
 static uint32 g_timeSecs;
@@ -687,13 +814,13 @@
 
 #define SECONDS_PER_DAY (24 * 60 * 60)
 
-void readRtcTime(void) {
+void OSystem_PS2::readRtcTime(void) {
 	struct CdClock cdClock;
 	CDVD_ReadClock(&cdClock);
-	g_lastTimeCheck = (uint32)(msecCount >> 32);
+	g_lastTimeCheck = msecCount;
 
 	if (cdClock.stat) {
-		printf("Unable to read RTC time, EC: %d\n", cdClock.stat);
+		msgPrintf(5000, "Unable to read RTC time, EC: %d\n", cdClock.stat);
 		g_day = g_month = 1;
 		g_year = 0;
 		g_timeSecs = 0;
@@ -717,7 +844,6 @@
 			buildNewDate(+1);
 			timeSecs -= SECONDS_PER_DAY;
 		}
-
 		g_timeSecs = (uint32)timeSecs;
 	}
 
@@ -726,17 +852,15 @@
 }
 
 extern time_t time(time_t *p) {
-	time_t blah;
-	memset(&blah, 0, sizeof(time_t));
-	return blah;
+	return (time_t)g_timeSecs;
 }
 
 extern struct tm *localtime(const time_t *p) {
-	uint32 currentSecs = g_timeSecs + ((msecCount >> 32) - g_lastTimeCheck) / 1000;
+	uint32 currentSecs = g_timeSecs + (msecCount - g_lastTimeCheck) / 1000;
 	if (currentSecs >= SECONDS_PER_DAY) {
 		buildNewDate(+1);
-		g_timeSecs -= SECONDS_PER_DAY;
-		currentSecs = g_timeSecs + ((msecCount >> 32) - g_lastTimeCheck) / 1000;
+		g_lastTimeCheck += SECONDS_PER_DAY * 1000;
+		currentSecs = g_timeSecs + (msecCount - g_lastTimeCheck) / 1000;
 	}
 
 	static struct tm retStruct;
@@ -747,7 +871,7 @@
 	retStruct.tm_sec  = currentSecs % 60;
 	retStruct.tm_year = g_year + 100;
 	retStruct.tm_mday = g_day;
-	retStruct.tm_mon  = g_month;
+	retStruct.tm_mon  = g_month - 1;
 	// tm_wday, tm_yday and tm_isdst are zero for now
     return &retStruct;
 }

Index: systemps2.h
===================================================================
RCS file: /cvsroot/scummvm/scummvm/backends/ps2/systemps2.h,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -d -r1.8 -r1.9
--- systemps2.h	18 Oct 2005 01:30:14 -0000	1.8
+++ systemps2.h	9 Nov 2005 19:51:57 -0000	1.9
@@ -29,6 +29,17 @@
 class Ps2Input;
 class Ps2SaveFileManager;
 
+#define _REC_MUTEX_
+
+#ifdef _REC_MUTEX_
+#define MAX_MUTEXES 32
+struct Ps2Mutex {
+	int sema;
+	int owner;
+	int count;
+};
+#endif
+
 class OSystem_PS2 : public OSystem {
 public:
 	OSystem_PS2(void);
@@ -38,11 +49,17 @@
 	virtual int16 getHeight(void);
 	virtual int16 getWidth(void);
 	virtual void setPalette(const byte *colors, uint start, uint num);
-	virtual void grabPalette(byte *colors, uint start, uint num);
 	virtual void copyRectToScreen(const byte *buf, int pitch, int x, int y, int w, int h);
-
-	virtual void updateScreen();
 	virtual void setShakePos(int shakeOffset);
+	virtual void grabPalette(byte *colors, uint start, uint num);
+	virtual bool grabRawScreen(Graphics::Surface *surf);
+	virtual void updateScreen();
+
+	virtual void showOverlay();
+	virtual void hideOverlay();
+	virtual void clearOverlay();
+	virtual void grabOverlay(OverlayColor *buf, int pitch);
+	virtual void copyRectToOverlay(const OverlayColor *buf, int pitch, int x, int y, int w, int h);
 
 	virtual bool showMouse(bool visible);
 
@@ -69,12 +86,6 @@
 	virtual void unlockMutex(MutexRef mutex);
 	virtual void deleteMutex(MutexRef mutex);
 
-	virtual void showOverlay();
-	virtual void hideOverlay();
-	virtual void clearOverlay();
-	virtual void grabOverlay(OverlayColor *buf, int pitch);
-	virtual void copyRectToOverlay(const OverlayColor *buf, int pitch, int x, int y, int w, int h);
-
 	virtual const GraphicsMode *getSupportedGraphicsModes() const;
 	virtual int getDefaultGraphicsMode() const;
 	virtual bool setGraphicsMode(int mode);
@@ -90,30 +101,36 @@
 
 	void timerThread(void);
 	void soundThread(void);
+	void msgPrintf(int millis, char *format, ...);
+
 private:
 	volatile OSystem::TimerProc _scummTimerProc;
 	volatile OSystem::SoundProc _scummSoundProc;
 	void *_scummSoundParam;
-	int16 *_soundBufL, *_soundBufR;
 	int _soundSema;
 
 	void initTimer(void);
-	void fatalError(char *str);
+	void readRtcTime(void);
 
-	bool loadModules(char *errorStr);
+	void loadModules(void);
 	bool _mouseVisible;
-	bool _useHdd, _useMouse, _useKbd;
+	bool _useMouse, _useKbd;
 
 	Ps2SaveFileManager *_saveManager;
 
-	uint16 _width, _height;
-
 	Gs2dScreen	*_screen;
 	Ps2Input	*_input;
 	uint16		_oldMouseX, _oldMouseY;
-
+	uint32		_msgClearTime;
+	uint16		_printY;
+#ifdef _REC_MUTEX_
+	int			_mutexSema;
+	Ps2Mutex	*_mutex;
+#endif
 	uint8		*_timerStack, *_soundStack;
-	int32		_timerTid, _soundTid;
+	int			_timerTid, _soundTid;
+	int			_intrId;
+	volatile bool _systemQuit;
 	static const GraphicsMode _graphicsMode;
 };
 

--- smushio.cpp DELETED ---





More information about the Scummvm-git-logs mailing list