⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 goboy.cpp

📁 gameboy 模拟器的源代码
💻 CPP
📖 第 1 页 / 共 2 页
字号:

// GOBOYEXE.CPP

#include "goboy.h"
#include "fb.h"
#include "input.h"
#include "gb_sound.h"

#include <aknglobalnote.h>
#include <ezlib.h>


_LIT(KNoMemoryNote,"Out of memory. Please close any running applications, or restart phone.");

enum TServerUiList
	{
	EOptionsMenu,
	ELoadGameMenu,
	EDeleteGameMenu,
	ESelectKeyQuery
	};

enum TOptionsListItem
	{
	EOptionSave,
	EOptionLoad,
	EOptionDelete,
	EOptionSound,
	EOptionKeys,
	EOptionSwap,
	EOptionExit
	};



extern "C"
	{
void gb_main (int argc, char** argv);
	};


extern "C" void PostEvent(int aScancode, int aDown);


extern "C"
	{
	unsigned char* vidptr();
	};

extern "C"
	{
	unsigned char* vid_toggle_enable();
	};

extern "C"
	{
	void doSaveState(char*);
	};

extern "C"
	{
	void doLoadState(char*);
	};

extern "C" 
	{
	void set_paused(int aPaused);
	};

extern "C"
	{
	void exit_emulator();
	};

extern "C"
	{
	void gbsetSoundMode(int aMode);
	};

extern "C"
	{
	void gb_reset();
	};

extern "C"
	{
	void vid_close();
	};

RFs TheFs;
CGoBoy* goBoy;
CServerUi* iServerUi = NULL;
CGBSound* iGBSound = NULL;
char loadbuf[4096];

const TInt KUnzipBufferSize = 8192;

#define MAX_FRAMESKIP 4

int frameskip;

CGoBoy::CGoBoy()
:iScreenUtil(NULL)
	{
	frameskip = 0;
	}

CGoBoy::~CGoBoy()
	{
	gb_reset();
	vid_close();
	delete iGBSound;
	delete iFrame;
	delete iServerUi;
	delete iMenuCba;
	delete iCba;
	delete iScreen;
	delete iWindowGc;
	delete iWsScreen;
	iWsSession.Close();
	}

void CGoBoy::ConstructL(const TDesC& aCommandLine)
	{
	TInt nameLength = aCommandLine.Locate('*');
	if (nameLength == KErrNotFound)
		{
		iImageName = aCommandLine;
		}
	else
		{
		iImageName.Copy(aCommandLine.Left(nameLength-1));
		}
	iArgc = 0;
	iSwapButtons = EFalse;

	User::LeaveIfError(iWsSession.Connect());
    iWsScreen=new(ELeave) CWsScreenDevice(iWsSession);
    User::LeaveIfError(iWsScreen->Construct());
    User::LeaveIfError(iWsScreen->CreateContext(iWindowGc));
	iWsWindowGroup=RWindowGroup(iWsSession);
    User::LeaveIfError(iWsWindowGroup.Construct((TUint32)this));
    iWsWindowGroup.SetOrdinalPosition(0);
    iWsWindow=RWindow(iWsSession);
    User::LeaveIfError(iWsWindow.Construct(iWsWindowGroup, (TUint32)this));
    iWsWindow.Activate();


	iWsWindow.SetExtent(TPoint(0,0), TSize(176,208));

    iWsWindow.SetVisible(ETrue);
    StartWServEvents();

	iGBSound = new(ELeave)CGBSound();

	iGBSound->ConstructL();

	}

void CGoBoy::StartWServEvents()
    {
     iWsEventStatus = KRequestPending;
     iWsSession.EventReady(&iWsEventStatus);            // get Window Server events
     iRedrawEventStatus = KRequestPending;
     iWsSession.RedrawReady(&iRedrawEventStatus);      // get server-initiated redraw events
    }


void CGoBoy::CreateScreenL()
	{
	iScreen = new(ELeave)CFbsBitmap();
	TSize size = TSize(160,144);

	iScreen->Create(size, EColor4K);

	iMenuCba = new(ELeave)CFbsBitmap();
	iMenuCba->Create(TSize(176, 20), EColor4K);

	iServerUi = new(ELeave)CServerUi();
	iServerUi->ConstructL(iWsScreen, iScreen, iMenuCba, this);

	RProcess process;
	TFileName appName = process.FileName();
	TParsePtrC parse(appName);
	TFileName name(parse.DriveAndPath());
	name.Append(_L("goboyapp.mbm"));


	iCba = new(ELeave)CFbsBitmap();
	TInt err = iCba->Load(name, 1);
	if (err != KErrNone)
		{
		delete iCba;
		iCba = NULL;
		}

	iFrame = new(ELeave)CFbsBitmap();
	err = iFrame->Load(name, 3);
	if (err != KErrNone)
		{
		delete iFrame;
		iFrame = NULL;
		}



	PrepareScreen();
	SetDefaultKeys();
	LoadSettingsL();
	SetSoundMode();
	}


void CGoBoy::PrepareScreen()
	{
	CFbsBitmapDevice* bitDev = CFbsBitmapDevice::NewL(iScreen);
	CleanupStack::PushL(bitDev);
	CFbsBitGc* bitGc = CFbsBitGc::NewL();
	CleanupStack::PushL(bitGc);
	bitGc->Activate(bitDev);
	bitGc->SetBrushColor(TRgb(0,0,0));
	bitGc->SetBrushStyle(CGraphicsContext::ESolidBrush);
	bitGc->Clear();

	// Draw to screen
    iWindowGc->Activate(iWsWindow);
    TRect rect = TRect(iWsWindow.Size());
    iWsWindow.Invalidate(rect);
    iWsWindow.BeginRedraw(rect);

	iWindowGc->SetBrushColor(TRgb(0,0,0));
	iWindowGc->SetBrushStyle(CGraphicsContext::ESolidBrush);
	iWindowGc->Clear();
	iWindowGc->BitBlt(TPoint(0,188), iCba);
	if (iFrame)
		{
		iWindowGc->BitBlt(TPoint(0,0), iFrame);
		}

    iWsWindow.EndRedraw();
    iWindowGc->Deactivate();
    iWsSession.Flush();

	CleanupStack::PopAndDestroy(2);
	iScreenUtil = TBitmapUtil(iScreen);
	}


void CGoBoy::Go()
	{
	gb_main(iArgc, iArgv);
	}


void CGoBoy::UpdateScreen()
	{
	iScreenUtil.Begin(TPoint(0,0));
	TUint32* dest = (TUint32*)(iScreen->DataAddress());

	TUint32* src = (TUint32*)iVidPtr;

	TInt size = 144*80;

	while (size)
		{
		*dest = *src;
		src++;
		dest++;
		size--;
		}

	iScreenUtil.End();


	if (iServerUi->iIsActive)
		{
		iServerUi->Draw(iScreen);
		}

    iWindowGc->Activate(iWsWindow);
    TRect rect = TRect(iWsWindow.Size());
    iWsWindow.Invalidate(rect);
    iWsWindow.BeginRedraw(rect);

	iWindowGc->BitBlt(TPoint(8,16),iScreen);

    iWsWindow.EndRedraw();
    iWindowGc->Deactivate();
    iWsSession.Flush();

	}


void CGoBoy::GetEvents()
	{
     if (iWsEventStatus != KRequestPending)
      {
          iWsSession.GetEvent(iWsEvent);

		  if (iWsEvent.Type() == EEventKeyDown)
			  {
			  if (iServerUi->iIsActive)
				  {
				  iServerUi->KeyEvent(iWsEvent.Key()->iScanCode);
				  }
			  else
				  {
				  SendKeyDown(iWsEvent.Key()->iScanCode);
				  }
			  }
		  else if (iWsEvent.Type() == EEventKeyUp)
			  {
			  SendKeyUp(iWsEvent.Key()->iScanCode);
			  }
		  else if (iWsEvent.Type() == EEventFocusLost)
			  {
			  set_paused(1);
			  RThread thread;
			  thread.SetPriority(EPriorityMuchLess);
			  }
		  else if (iWsEvent.Type() == EEventFocusGained)
			  {
			  RThread thread;
			  thread.SetPriority(EPriorityNormal);
			  PrepareScreen();
			  }
          iWsEventStatus = KRequestPending;
          iWsSession.EventReady(&iWsEventStatus);
      }
	}




TInt CGoBoy::MapScanCode(TInt aScanCode)
	{
	if (aScanCode == iKeySelect[0])
		{
		return K_UP;
		}
	if (aScanCode == iKeySelect[1])
		{
		return K_DOWN;
		}
	if (aScanCode == iKeySelect[2])
		{
		return K_LEFT;
		}
	if (aScanCode == iKeySelect[3])
		{
		return K_RIGHT;
		}
	if (aScanCode == iKeySelect[4])
		{
		if (iSwapButtons)
			{
			return 's';	// Button B
			}
		else
			{
			return 'd';	// Button A
			}
		}
	if (aScanCode == iKeySelect[5])
		{
		if (iSwapButtons)
			{
			return 'd';	// Button A
			}
		else
			{
			return 's';	// Button B
			}
		}

	switch (aScanCode)
		{
		case EStdKeyEnter:
		case EStdKeyDevice1:
			return K_ENTER;	// Start
		case EStdKeySpace:
		case EStdKeyDevice0:
			return K_SPACE;	// Select
		case EStdKeyBackspace:
			return K_CTRL;
	default:
		return 0;
		}
	}


void CGoBoy::ProcessSaveL()
	{
	// GetNameForSaving
	TInt index = 1;
	TBool isUniqueName = EFalse;
	TFileName name;
	goBoy->AppendSaveGameDirectory(name);
	goBoy->AppendNameOfGame(name);


	TInt len = name.Length();
	while (!isUniqueName)
		{
		name.AppendFormat(_L(".%03d"), index);
		TEntry entry;
		if (TheFs.Entry(name, entry) == KErrNone)
			{
			index++;
			name.SetLength(len);
			}
		else
			{
			isUniqueName = ETrue;
			}
		}

	char fName[256];
	len = name.Length();
	for (TInt ii=0; ii<len; ii++)
		{
		fName[ii] = name[ii];
		}
	fName[ii] = 0;
	doSaveState(fName);

	TBuf<20> buffer;
	buffer.Format(_L("Game %03d saved"), index);
	ShowNoteL(_L("Saved..."), buffer);
	}

void CGoBoy::ProcessLoadL(TBool aDelete)
	{
	}



void CGoBoy::SendKeyDown(TInt aScanCode)
	{
	PostEvent(MapScanCode(aScanCode), 1);
	}

void CGoBoy::SendKeyUp(TInt aScanCode)
	{
	PostEvent(MapScanCode(aScanCode), 0);
	}

void CGoBoy::SetVidPtr(unsigned char* aVidPtr)
	{
	iVidPtr = aVidPtr;
	}

void CGoBoy::OpenFile(char* /*aName*/)
	{
	TInt loc;
	if ((loc = iImageName.Locate('#')) != KErrNotFound)
		{
		// Open Zip File
		TPtrC zipName = iImageName.Left(loc);
		TPtrC rest = iImageName.Mid(loc+1);
		loc = rest.Locate('#');
		TPtrC rest2 = rest.Mid(loc+1);
		loc = rest2.Locate('#');
		TLex lex(rest2.Left(loc));
		lex.Val(iZipOffset);
		TPtrC rest3 = rest2.Mid(loc+1);
		loc = rest3.Locate('#');
		TLex lex2(rest3.Left(loc));
		lex2.Val(iZipCSize);
		TLex lex3(rest3.Mid(loc+1));
		lex3.Val(iZipUSize);

		TInt err = iStream.Open(TheFs, zipName, EFileRead);
		}
	else
		{
		TInt err = iStream.Open(TheFs, iImageName, EFileRead);
		iZipOffset = 0;
		}
	}

void CGoBoy::CloseFile()
	{
	iStream.Close();
	}

void CGoBoy::ReadL(unsigned char* aDest, TInt aSize)
	{
	if (iZipOffset == 0)
		{
		iStream.ReadL(aDest, aSize);
		}
	else
		{
		// Unpack zip file
		HBufC8* buffer = HBufC8::NewMaxLC(KUnzipBufferSize);
		TPtr8 bufPtr = buffer->Des();

		TInt totalSize = iZipCSize;
		TInt next = KUnzipBufferSize;
		if (totalSize < next)
			{
			next = totalSize;
			}

		iStream.ReadL(iZipOffset);

		iStream.ReadL(bufPtr,next);

		z_stream stream;
		int err;

		stream.next_in = (Bytef*)bufPtr.Ptr();
		stream.avail_in = (uInt)next;

		stream.next_out = aDest;
		stream.avail_out = iZipUSize;

		stream.zalloc = (alloc_func)0;
		stream.zfree = (free_func)0;

		err = inflateInit2(&stream, -15);
		if (err != Z_OK)
			{
			User::Leave(KErrCorrupt);
			};

		while (err == Z_OK && totalSize > 0)
			{
			err = inflate(&stream, Z_SYNC_FLUSH);
			totalSize -= next;
			if (totalSize > 0)
				{
				next = KUnzipBufferSize;
				if (totalSize < next)
					{
					next = totalSize;
					}
				iStream.ReadL(bufPtr,next);
				stream.next_in = (Bytef*)bufPtr.Ptr();
				stream.avail_in = (uInt)next;
				}
			}

		err = inflateEnd(&stream);


		CleanupStack::PopAndDestroy(buffer);
		}
	}

int CGoBoy::FileSize(char* /*aName*/)
	{
	TInt loc;
	if ((loc = iImageName.Locate('#')) != KErrNotFound)
		{
		TInt size;
		TPtrC rest = iImageName.Mid(loc+1);
		loc = rest.Locate('#');
		TPtrC rest2 = rest.Mid(loc+1);
		loc = rest2.Locate('#');
		TPtrC rest3 = rest2.Mid(loc+1);
		loc = rest3.Locate('#');
		TLex lex3(rest3.Mid(loc+1));
		lex3.Val(size);
		return size;
		}
	else
		{
		TEntry entry;
		TInt err = TheFs.Entry(iImageName, entry);
		if (err == KErrNone)
			{
			return entry.iSize;
			}
		else
			{
			return 0;
			}
		}
	}

void CGoBoy::ShowNoteL(const TDesC& aTitle, const TDesC& aNote)
	{
	iServerUi->CreateNoteL(aTitle, aNote);
	iServerUi->Activate(ETrue);
	set_paused(1);
	}

void CGoBoy::AppendSaveGameDirectory(TDes& aName)
	{
	RProcess process;
	TFileName appName = process.FileName();
	TParsePtrC parse(appName);
	TFileName name(parse.DriveAndPath());
	name.Append(_L("save\\"));
	TheFs.MkDirAll(name);
	aName.Append(name);
	}

void CGoBoy::AppendNameOfGame(TDes& aName)
	{
	TInt loc;
	if ((loc = iImageName.Locate('#')) != KErrNotFound)
		{
		// Open Zip File
		TPtrC zipName = iImageName.Left(loc);
		TPtrC rest = iImageName.Mid(loc+1);
		loc = rest.Locate('#');
		TParsePtrC parse(rest.Left(loc));
		aName.Append(parse.Name());
		}
	else
		{
		TParsePtrC parse(iImageName);
		aName.Append(parse.Name());
		}
	}



extern "C" void memcpy()

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -