📄 goboy.cpp
字号:
// 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 + -