From 51317997f5e7e192c2fd545d7de759e2a04188b7 Mon Sep 17 00:00:00 2001 From: Shawn Hoffman Date: Sun, 17 Aug 2008 16:41:53 +0000 Subject: [PATCH] changed dolphinWX a bit and added memcard manager git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@234 8ced0084-cf51-0410-be5f-012b33b47a6e --- Source/Core/DolphinWX/src/Frame.cpp | 248 ++++------- Source/Core/DolphinWX/src/Frame.h | 3 +- Source/Core/DolphinWX/src/Globals.h | 2 + Source/Core/DolphinWX/src/MemcardManager.cpp | 254 +++++++++++ Source/Core/DolphinWX/src/MemcardManager.h | 91 ++++ .../DolphinWX/src/MemoryCards/GCMemcard.cpp | 394 ++++++++++++++++++ .../DolphinWX/src/MemoryCards/GCMemcard.h | 159 +++++++ Source/Core/DolphinWX/src/PluginOptions.cpp | 154 +++---- Source/Core/DolphinWX/src/PluginOptions.h | 16 +- 9 files changed, 1059 insertions(+), 262 deletions(-) create mode 100644 Source/Core/DolphinWX/src/MemcardManager.cpp create mode 100644 Source/Core/DolphinWX/src/MemcardManager.h create mode 100644 Source/Core/DolphinWX/src/MemoryCards/GCMemcard.cpp create mode 100644 Source/Core/DolphinWX/src/MemoryCards/GCMemcard.h diff --git a/Source/Core/DolphinWX/src/Frame.cpp b/Source/Core/DolphinWX/src/Frame.cpp index 5716a9b2d7..4de8591b3b 100644 --- a/Source/Core/DolphinWX/src/Frame.cpp +++ b/Source/Core/DolphinWX/src/Frame.cpp @@ -26,6 +26,7 @@ #include "Core.h" #include "PluginOptions.h" #include "PluginManager.h" +#include "MemcardManager.h" #include "wx/mstream.h" @@ -88,9 +89,11 @@ EVT_MENU(IDM_CONFIG_GFX_PLUGIN, CFrame::OnPluginGFX) EVT_MENU(IDM_CONFIG_DSP_PLUGIN, CFrame::OnPluginDSP) EVT_MENU(IDM_CONFIG_PAD_PLUGIN, CFrame::OnPluginPAD) EVT_MENU(IDM_BROWSE, CFrame::OnBrowse) +EVT_MENU(IDM_MEMCARD, CFrame::OnMemcard) EVT_MENU(IDM_TOGGLE_FULLSCREEN, CFrame::OnToggleFullscreen) EVT_MENU(IDM_TOGGLE_DUALCORE, CFrame::OnToggleDualCore) EVT_MENU(IDM_TOGGLE_THROTTLE, CFrame::OnToggleThrottle) +EVT_MENU(IDM_TOGGLE_TOOLBAR, CFrame::OnToggleToolbar) EVT_HOST_COMMAND(wxID_ANY, CFrame::OnHostMessage) END_EVENT_TABLE() @@ -154,136 +157,68 @@ CFrame::CFrame(wxFrame* parent, } -void -CFrame::CreateMenu() +void CFrame::CreateMenu() { delete m_pMenuBar; m_pMenuBar = new wxMenuBar(wxMB_DOCKABLE); // file menu - { - wxMenu* fileMenu = new wxMenu; - { - wxMenuItem* pItem = fileMenu->Append(wxID_OPEN, _T("&Open...")); - pItem->SetBitmap(m_BitmapsMenu[Toolbar_FileOpen]); - } - { - wxMenuItem* pItem = fileMenu->Append(wxID_REFRESH, _T("&Refresh")); - pItem->SetBitmap(m_BitmapsMenu[Toolbar_Refresh]); - } + wxMenu* fileMenu = new wxMenu; + fileMenu->Append(wxID_OPEN, _T("&Open...")); + fileMenu->Append(wxID_REFRESH, _T("&Refresh")); + fileMenu->Append(IDM_BROWSE, _T("&Browse for ISOs...")); + fileMenu->AppendSeparator(); + m_pMenuItemPlay = new wxMenuItem(fileMenu, IDM_PLAY, _T("&Play")); + fileMenu->Append(m_pMenuItemPlay); + m_pMenuItemStop = new wxMenuItem(fileMenu, IDM_STOP, _T("&Stop")); + fileMenu->Append(m_pMenuItemStop); - { - wxMenuItem* pItem = fileMenu->Append(IDM_BROWSE, _T("&Browse for ISOs...")); - pItem->SetBitmap(m_BitmapsMenu[Toolbar_Browse]); - } -/* - fileMenu->AppendSeparator(); - wxMenuItem* LoadState = fileMenu->Append(IDM_LOADSTATE, _T("&Load State...")); - LoadState->Enable(false); - wxMenuItem* SaveState = fileMenu->Append(IDM_SAVESTATE, _T("&Save State...")); - SaveState->Enable(false); -*/ - fileMenu->AppendSeparator(); - fileMenu->Append(wxID_EXIT, _T("E&xit"), _T("")); - m_pMenuBar->Append(fileMenu, _T("&File")); - } + /*fileMenu->AppendSeparator(); + wxMenuItem* LoadState = fileMenu->Append(IDM_LOADSTATE, _T("&Load State...")); + LoadState->Enable(false); + wxMenuItem* SaveState = fileMenu->Append(IDM_SAVESTATE, _T("&Save State...")); + SaveState->Enable(false);*/ - // Game menu - { - wxMenu* pGameMenu = new wxMenu; - { - wxMenuItem *pItem = new wxMenuItem(pGameMenu, IDM_EDITPATCHFILE, wxString::FromAscii("Edit patch file")); - pGameMenu->Append(pItem); - } - } + fileMenu->AppendSeparator(); + fileMenu->Append(wxID_EXIT, _T("E&xit"), _T("")); + m_pMenuBar->Append(fileMenu, _T("&File")); - // emulation menu - { - wxMenu* pEmulationMenu = new wxMenu; - // play - { - m_pMenuItemPlay = new wxMenuItem(pEmulationMenu, IDM_PLAY, _T("&Play")); - m_pMenuItemPlay->SetBitmap(m_BitmapsMenu[Toolbar_Play]); - #ifdef WIN32 - m_pMenuItemPlay->SetDisabledBitmap(m_BitmapsMenu[Toolbar_Play_Dis]); //Linux Doesn't have - #endif - pEmulationMenu->Append(m_pMenuItemPlay); - } - // stop - { - m_pMenuItemStop = new wxMenuItem(pEmulationMenu, IDM_STOP, _T("&Stop")); - m_pMenuItemStop->SetBitmap(m_BitmapsMenu[Toolbar_Stop]); - #ifdef WIN32 - m_pMenuItemStop->SetDisabledBitmap(m_BitmapsMenu[Toolbar_Stop_Dis]); //Linux doesn't have - #endif - pEmulationMenu->Append(m_pMenuItemStop); - } - pEmulationMenu->AppendSeparator(); - { - // full screen - wxMenuItem* pItem = new wxMenuItem(pEmulationMenu, IDM_TOGGLE_FULLSCREEN, _T("&Fullscreen")); - pItem->SetBitmap(m_BitmapsMenu[Toolbar_FullScreen]); - pEmulationMenu->Append(pItem); - } - { - // dual core - wxMenuItem* pItem = new wxMenuItem(pEmulationMenu, IDM_TOGGLE_DUALCORE, _T("&Dual Core (instable!)"), wxEmptyString, wxITEM_CHECK); - pEmulationMenu->Append(pItem); - pItem->Check(SConfig::GetInstance().m_LocalCoreStartupParameter.bUseDualCore); - } - { - // throttling - wxMenuItem* pItem = new wxMenuItem(pEmulationMenu, IDM_TOGGLE_THROTTLE, _T("&Speed throttle"), wxEmptyString, wxITEM_CHECK); - pEmulationMenu->Append(pItem); - pItem->Check(SConfig::GetInstance().m_LocalCoreStartupParameter.bThrottle); - } - m_pMenuBar->Append(pEmulationMenu, _T("&Emulation")); - } + // options menu + wxMenu* pOptionsMenu = new wxMenu; + m_pPluginOptions = new wxMenuItem(pOptionsMenu, IDM_PLUGIN_OPTIONS, _T("&Select plugins")); + pOptionsMenu->Append(m_pPluginOptions); + pOptionsMenu->AppendSeparator(); + pOptionsMenu->Append(IDM_CONFIG_GFX_PLUGIN, _T("&GFX settings")); + pOptionsMenu->Append(IDM_CONFIG_DSP_PLUGIN, _T("&DSP settings")); + pOptionsMenu->Append(IDM_CONFIG_PAD_PLUGIN, _T("&PAD settings")); + pOptionsMenu->AppendSeparator(); + pOptionsMenu->Append(IDM_TOGGLE_FULLSCREEN, _T("&Fullscreen")); + pOptionsMenu->AppendCheckItem(IDM_TOGGLE_DUALCORE, _T("&Dual-core (instable!)")); + pOptionsMenu->Check(IDM_TOGGLE_DUALCORE, SConfig::GetInstance().m_LocalCoreStartupParameter.bUseDualCore); + pOptionsMenu->AppendCheckItem(IDM_TOGGLE_THROTTLE, _T("&Enable throttle")); + pOptionsMenu->Check(IDM_TOGGLE_THROTTLE, SConfig::GetInstance().m_LocalCoreStartupParameter.bThrottle); + m_pMenuBar->Append(pOptionsMenu, _T("&Options")); - // plugin menu - { - wxMenu* pPluginMenu = new wxMenu; - { - m_pPluginOptions = pPluginMenu->Append(IDM_PLUGIN_OPTIONS, _T("&Choose Plugins...")); - m_pPluginOptions->SetBitmap(m_BitmapsMenu[Toolbar_PluginOptions]); - #ifdef WIN32 - m_pPluginOptions->SetDisabledBitmap(m_BitmapsMenu[Toolbar_PluginOptions_Dis]); //Linux doesn't have - #endif - } - pPluginMenu->AppendSeparator(); - { - wxMenuItem* pItem = pPluginMenu->Append(IDM_CONFIG_GFX_PLUGIN, _T("&GFX plugin settings...")); - pItem->SetBitmap(m_BitmapsMenu[Toolbar_PluginGFX]); - } - { - wxMenuItem* pItem = pPluginMenu->Append(IDM_CONFIG_DSP_PLUGIN, _T("&DSP plugin settings...")); - pItem->SetBitmap(m_BitmapsMenu[Toolbar_PluginDSP]); - } - { - wxMenuItem* pItem = pPluginMenu->Append(IDM_CONFIG_PAD_PLUGIN, _T("&PAD plugin settings...")); - pItem->SetBitmap(m_BitmapsMenu[Toolbar_PluginPAD]); - } - m_pMenuBar->Append(pPluginMenu, _T("&Plugins")); - } + // misc menu + wxMenu* miscMenu = new wxMenu; + miscMenu->Append(IDM_MEMCARD, _T("&Memory card manager")); + miscMenu->AppendCheckItem(IDM_TOGGLE_TOOLBAR, _T("&Enable toolbar")); + miscMenu->Check(IDM_TOGGLE_TOOLBAR, true); + m_pMenuBar->Append(miscMenu, _T("&Misc")); // help menu - { - wxMenu* helpMenu = new wxMenu; - { - wxMenuItem* pItem = helpMenu->Append(wxID_HELP, _T("&Help")); - pItem->SetBitmap(m_BitmapsMenu[Toolbar_Help]); - } - helpMenu->Append(wxID_HELP, _T("&About...")); - m_pMenuBar->Append(helpMenu, _T("&Help")); - } + wxMenu* helpMenu = new wxMenu; + /*helpMenu->Append(wxID_HELP, _T("&Help")); + re-enable when there's something useful to display*/ + helpMenu->Append(wxID_HELP, _T("&About...")); + m_pMenuBar->Append(helpMenu, _T("&Help")); // Associate the menu bar with the frame SetMenuBar(m_pMenuBar); } -void -CFrame::PopulateToolbar(wxToolBar* toolBar) +void CFrame::PopulateToolbar(wxToolBar* toolBar) { int w = m_Bitmaps[Toolbar_FileOpen].GetWidth(), h = m_Bitmaps[Toolbar_FileOpen].GetHeight(); @@ -299,11 +234,11 @@ CFrame::PopulateToolbar(wxToolBar* toolBar) toolBar->SetToolDisabledBitmap(IDM_STOP, m_Bitmaps[Toolbar_Stop_Dis]); toolBar->AddTool(IDM_TOGGLE_FULLSCREEN, _T("Fullscr."), m_Bitmaps[Toolbar_FullScreen], _T("Toggle Fullscreen")); toolBar->AddSeparator(); - toolBar->AddTool(IDM_PLUGIN_OPTIONS, _T("Plugins"), m_Bitmaps[Toolbar_PluginOptions], _T("Plugin Selection...")); + toolBar->AddTool(IDM_PLUGIN_OPTIONS, _T("Plugins"), m_Bitmaps[Toolbar_PluginOptions], _T("Select plugins")); toolBar->SetToolDisabledBitmap(IDM_PLUGIN_OPTIONS, m_Bitmaps[Toolbar_PluginOptions_Dis]); - toolBar->AddTool(IDM_CONFIG_GFX_PLUGIN, _T("GFX"), m_Bitmaps[Toolbar_PluginGFX], _T("GFX Plugin...")); - toolBar->AddTool(IDM_CONFIG_DSP_PLUGIN, _T("DSP"), m_Bitmaps[Toolbar_PluginDSP], _T("DSP Plugin...")); - toolBar->AddTool(IDM_CONFIG_PAD_PLUGIN, _T("PAD"), m_Bitmaps[Toolbar_PluginPAD], _T("PAD Plugin...")); + toolBar->AddTool(IDM_CONFIG_GFX_PLUGIN, _T("GFX"), m_Bitmaps[Toolbar_PluginGFX], _T("GFX settings")); + toolBar->AddTool(IDM_CONFIG_DSP_PLUGIN, _T("DSP"), m_Bitmaps[Toolbar_PluginDSP], _T("DSP settings")); + toolBar->AddTool(IDM_CONFIG_PAD_PLUGIN, _T("PAD"), m_Bitmaps[Toolbar_PluginPAD], _T("PAD settings")); toolBar->AddSeparator(); toolBar->AddTool(wxID_HELP, _T("About"), m_Bitmaps[Toolbar_Help], _T("About Dolphin")); @@ -313,8 +248,7 @@ CFrame::PopulateToolbar(wxToolBar* toolBar) } -void -CFrame::RecreateToolbar() +void CFrame::RecreateToolbar() { // delete and recreate the toolbar wxToolBarBase* toolBar = GetToolBar(); @@ -331,8 +265,7 @@ CFrame::RecreateToolbar() } -void -CFrame::InitBitmaps() +void CFrame::InitBitmaps() { // load orignal size 48x48 m_Bitmaps[Toolbar_FileOpen] = wxGetBitmapFromMemory(toolbar_file_open_png); @@ -356,17 +289,10 @@ CFrame::InitBitmaps() { m_Bitmaps[n] = wxBitmap(m_Bitmaps[n].ConvertToImage().Scale(24, 24)); } - - // scale to 15x15 for menu - for (size_t n = Toolbar_FileOpen; n < WXSIZEOF(m_Bitmaps); n++) - { - m_BitmapsMenu[n] = wxBitmap(m_Bitmaps[n].ConvertToImage().Scale(15, 15)); - } } -void -CFrame::OnOpen(wxCommandEvent& WXUNUSED (event)) +void CFrame::OnOpen(wxCommandEvent& WXUNUSED (event)) { if (Core::GetState() != Core::CORE_UNINITIALIZED) return; @@ -391,8 +317,7 @@ CFrame::OnOpen(wxCommandEvent& WXUNUSED (event)) } -void -CFrame::OnQuit(wxCommandEvent& WXUNUSED (event)) +void CFrame::OnQuit(wxCommandEvent& WXUNUSED (event)) { if (Core::GetState() != Core::CORE_UNINITIALIZED) { @@ -404,8 +329,7 @@ CFrame::OnQuit(wxCommandEvent& WXUNUSED (event)) } -void -CFrame::OnAbout(wxCommandEvent& WXUNUSED (event)) +void CFrame::OnAbout(wxCommandEvent& WXUNUSED (event)) { wxAboutDialogInfo info; info.AddDeveloper(_T("ector")); @@ -424,15 +348,13 @@ CFrame::OnAbout(wxCommandEvent& WXUNUSED (event)) } -void -CFrame::OnHelp(wxCommandEvent& WXUNUSED (event)) +void CFrame::OnHelp(wxCommandEvent& WXUNUSED (event)) { wxMessageBox(wxString::FromAscii("missing OnHelp()")); } -void -CFrame::OnPlay(wxCommandEvent& WXUNUSED (event)) +void CFrame::OnPlay(wxCommandEvent& WXUNUSED (event)) { if (Core::GetState() != Core::CORE_UNINITIALIZED) { @@ -450,8 +372,7 @@ CFrame::OnPlay(wxCommandEvent& WXUNUSED (event)) } -void -CFrame::OnStop(wxCommandEvent& WXUNUSED (event)) +void CFrame::OnStop(wxCommandEvent& WXUNUSED (event)) { if (Core::GetState() != Core::CORE_UNINITIALIZED) { @@ -461,8 +382,7 @@ CFrame::OnStop(wxCommandEvent& WXUNUSED (event)) } -void -CFrame::OnRefresh(wxCommandEvent& WXUNUSED (event)) +void CFrame::OnRefresh(wxCommandEvent& WXUNUSED (event)) { if (m_GameListCtrl) { @@ -471,16 +391,14 @@ CFrame::OnRefresh(wxCommandEvent& WXUNUSED (event)) } -void -CFrame::OnPluginOptions(wxCommandEvent& WXUNUSED (event)) +void CFrame::OnPluginOptions(wxCommandEvent& WXUNUSED (event)) { CPluginOptions PluginOptions(this); PluginOptions.ShowModal(); } -void -CFrame::OnPluginGFX(wxCommandEvent& WXUNUSED (event)) +void CFrame::OnPluginGFX(wxCommandEvent& WXUNUSED (event)) { CPluginManager::GetInstance().OpenConfig( GetHandle(), @@ -489,8 +407,7 @@ CFrame::OnPluginGFX(wxCommandEvent& WXUNUSED (event)) } -void -CFrame::OnPluginDSP(wxCommandEvent& WXUNUSED (event)) +void CFrame::OnPluginDSP(wxCommandEvent& WXUNUSED (event)) { CPluginManager::GetInstance().OpenConfig( GetHandle(), @@ -499,8 +416,7 @@ CFrame::OnPluginDSP(wxCommandEvent& WXUNUSED (event)) } -void -CFrame::OnPluginPAD(wxCommandEvent& WXUNUSED (event)) +void CFrame::OnPluginPAD(wxCommandEvent& WXUNUSED (event)) { CPluginManager::GetInstance().OpenConfig( GetHandle(), @@ -508,16 +424,18 @@ CFrame::OnPluginPAD(wxCommandEvent& WXUNUSED (event)) ); } - -void -CFrame::OnBrowse(wxCommandEvent& WXUNUSED (event)) +void CFrame::OnBrowse(wxCommandEvent& WXUNUSED (event)) { m_GameListCtrl->BrowseForDirectory(); } +void CFrame::OnMemcard(wxCommandEvent& WXUNUSED (event)) +{ + CMemcardManager MemcardManager(this); + MemcardManager.ShowModal(); +} -void -CFrame::OnHostMessage(wxCommandEvent& event) +void CFrame::OnHostMessage(wxCommandEvent& event) { switch (event.GetId()) { @@ -561,14 +479,12 @@ CFrame::OnHostMessage(wxCommandEvent& event) } } - void CFrame::OnToggleFullscreen(wxCommandEvent& WXUNUSED (event)) { ShowFullScreen(true); UpdateGUI(); } - void CFrame::OnToggleDualCore(wxCommandEvent& WXUNUSED (event)) { SConfig::GetInstance().m_LocalCoreStartupParameter.bUseDualCore = !SConfig::GetInstance().m_LocalCoreStartupParameter.bUseDualCore; @@ -581,6 +497,21 @@ void CFrame::OnToggleThrottle(wxCommandEvent& WXUNUSED (event)) SConfig::GetInstance().SaveSettings(); } +void CFrame::OnToggleToolbar(wxCommandEvent& event) +{ + wxToolBarBase* toolBar = GetToolBar(); + + if (event.IsChecked()) + { + CFrame::RecreateToolbar(); + } + else + { + delete toolBar; + SetToolBar(NULL); + } +} + void CFrame::OnKeyDown(wxKeyEvent& event) { if (((event.GetKeyCode() == WXK_RETURN) && (event.GetModifiers() == wxMOD_ALT)) || @@ -595,7 +526,6 @@ void CFrame::OnKeyDown(wxKeyEvent& event) } } - void CFrame::UpdateGUI() { // buttons @@ -627,7 +557,6 @@ void CFrame::UpdateGUI() GetToolBar()->SetToolNormalBitmap(IDM_PLAY, m_Bitmaps[Toolbar_Pause]); GetToolBar()->SetToolShortHelp(IDM_PLAY, _T("Pause")); - m_pMenuItemPlay->SetBitmap(m_BitmapsMenu[Toolbar_Pause]); m_pMenuItemPlay->SetText(_T("Pause")); } else @@ -635,7 +564,6 @@ void CFrame::UpdateGUI() GetToolBar()->SetToolNormalBitmap(IDM_PLAY, m_Bitmaps[Toolbar_Play]); GetToolBar()->SetToolShortHelp(IDM_PLAY, _T("Play")); - m_pMenuItemPlay->SetBitmap(m_BitmapsMenu[Toolbar_Play]); m_pMenuItemPlay->SetText(_T("Play")); } } @@ -661,5 +589,3 @@ void CFrame::UpdateGUI() } } } - - diff --git a/Source/Core/DolphinWX/src/Frame.h b/Source/Core/DolphinWX/src/Frame.h index e8b9447175..634829724b 100644 --- a/Source/Core/DolphinWX/src/Frame.h +++ b/Source/Core/DolphinWX/src/Frame.h @@ -64,9 +64,11 @@ class CFrame void OnPlay(wxCommandEvent& event); void OnStop(wxCommandEvent& event); void OnBrowse(wxCommandEvent& event); + void OnMemcard(wxCommandEvent& event); void OnToggleFullscreen(wxCommandEvent& event); void OnToggleDualCore(wxCommandEvent& event); void OnToggleThrottle(wxCommandEvent& event); + void OnToggleToolbar(wxCommandEvent& event); void OnKeyDown(wxKeyEvent& event); void OnHostMessage(wxCommandEvent& event); @@ -90,4 +92,3 @@ class CFrame #endif // __FRAME_H_ - diff --git a/Source/Core/DolphinWX/src/Globals.h b/Source/Core/DolphinWX/src/Globals.h index 86506ddcba..f52e4b2368 100644 --- a/Source/Core/DolphinWX/src/Globals.h +++ b/Source/Core/DolphinWX/src/Globals.h @@ -25,6 +25,7 @@ enum IDM_PLAY, IDM_STOP, IDM_BROWSE, + IDM_MEMCARD, IDM_EDITPATCHFILE, IDM_OPENCONTAININGFOLDER, IDM_PLUGIN_OPTIONS, @@ -34,6 +35,7 @@ enum IDM_TOGGLE_FULLSCREEN, IDM_TOGGLE_DUALCORE, IDM_TOGGLE_THROTTLE, + IDM_TOGGLE_TOOLBAR, IDM_NOTIFYMAPLOADED, IDM_UPDATELOGDISPLAY, IDM_UPDATEDISASMDIALOG, diff --git a/Source/Core/DolphinWX/src/MemcardManager.cpp b/Source/Core/DolphinWX/src/MemcardManager.cpp new file mode 100644 index 0000000000..144f9be773 --- /dev/null +++ b/Source/Core/DolphinWX/src/MemcardManager.cpp @@ -0,0 +1,254 @@ +// Copyright (C) 2003-2008 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + +#include "Globals.h" + +#include "MemcardManager.h" + +BEGIN_EVENT_TABLE(CMemcardManager, wxDialog) + EVT_CLOSE(CMemcardManager::OnClose) + EVT_RIGHT_DOWN(CMemcardManager::OnRightClick) + EVT_BUTTON(ID_COPYRIGHT,CMemcardManager::CopyClick) + EVT_BUTTON(ID_COPYLEFT,CMemcardManager::CopyClick) + EVT_BUTTON(ID_DELETERIGHT,CMemcardManager::DeleteClick) + EVT_BUTTON(ID_DELETELEFT,CMemcardManager::DeleteClick) + EVT_FILEPICKER_CHANGED(ID_MEMCARD1PATH,CMemcardManager::OnPathChange) + EVT_FILEPICKER_CHANGED(ID_MEMCARD2PATH,CMemcardManager::OnPathChange) +END_EVENT_TABLE() + +CMemcardManager::CMemcardManager(wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& position, const wxSize& size, long style) + : wxDialog(parent, id, title, position, size, style) +{ + CreateGUIControls(); +} + +CMemcardManager::~CMemcardManager() +{ +} + +void CMemcardManager::CreateGUIControls() +{ + // buttons + m_CopyRight = new wxButton(this, ID_COPYRIGHT, wxT("->Copy->"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator); + m_CopyLeft = new wxButton(this, ID_COPYLEFT, wxT("<-Copy<-"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator); + + m_DeleteRight = new wxButton(this, ID_DELETERIGHT, wxT("Delete->"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator); + m_DeleteLeft = new wxButton(this, ID_DELETELEFT, wxT("<-Delete"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator); + + // sizers that double as wxStaticBoxes + sMemcard1 = new wxStaticBoxSizer(wxVERTICAL, this, wxT("Memory Card 1")); + sMemcard2 = new wxStaticBoxSizer(wxVERTICAL, this, wxT("Memory Card 2")); + + // create the controls for both memcards + // will change Mem*.raw to *.raw, when loading invalid .raw files doesn't crash the app :/ + m_Memcard1Path = new wxFilePickerCtrl(this, ID_MEMCARD1PATH, wxEmptyString, wxT("Choose a memory card:"), + wxT("Dolphin memcards (Mem*.raw)|Mem*.raw"), wxDefaultPosition, wxDefaultSize, wxFLP_USE_TEXTCTRL|wxFLP_FILE_MUST_EXIST|wxFLP_OPEN); + m_Memcard2Path = new wxFilePickerCtrl(this, ID_MEMCARD2PATH, wxEmptyString, wxT("Choose a memory card:"), + wxT("Dolphin memcards (Mem*.raw)|Mem*.raw"), wxDefaultPosition, wxDefaultSize, wxFLP_USE_TEXTCTRL|wxFLP_FILE_MUST_EXIST|wxFLP_OPEN); + + m_Memcard1List = new wxListCtrl(this, ID_MEMCARD1LIST, wxDefaultPosition, wxSize(500,400), + wxLC_REPORT | wxSUNKEN_BORDER | wxLC_ALIGN_LEFT | wxLC_SINGLE_SEL | wxLC_SORT_ASCENDING); + m_Memcard2List = new wxListCtrl(this, ID_MEMCARD2LIST, wxDefaultPosition, wxSize(500,400), + wxLC_REPORT | wxSUNKEN_BORDER | wxLC_ALIGN_LEFT | wxLC_SINGLE_SEL | wxLC_SORT_ASCENDING); + + // mmmm sizer goodness + wxBoxSizer* sButtons; + sButtons = new wxBoxSizer(wxVERTICAL); + sButtons->AddStretchSpacer(1); + sButtons->Add(m_CopyRight, 0, 0, 5); + sButtons->Add(m_CopyLeft, 0, 0, 5); + sButtons->Add(m_DeleteRight, 0, 0, 5); + sButtons->Add(m_DeleteLeft, 0, 0, 5); + sButtons->AddStretchSpacer(1); + + sMemcard1->Add(m_Memcard1Path, 0, wxEXPAND|wxALL, 5); + sMemcard1->Add(m_Memcard1List, 1, wxEXPAND|wxALL, 5); + sMemcard2->Add(m_Memcard2Path, 0, wxEXPAND|wxALL, 5); + sMemcard2->Add(m_Memcard2List, 1, wxEXPAND|wxALL, 5); + + //wxBoxSizer* sMain; + sMain = new wxBoxSizer(wxHORIZONTAL); + sMain->Add(sMemcard1, 1, wxEXPAND|wxALL, 5); + sMain->Add(sButtons, 0, wxEXPAND, 0); + sMain->Add(sMemcard2, 1, wxEXPAND|wxALL, 5); + + CenterOnParent(); + this->SetSizer(sMain); + sMain->SetSizeHints(this); +} + +void CMemcardManager::OnClose(wxCloseEvent& WXUNUSED (event)) +{ + Destroy(); +} + +void CMemcardManager::OnPathChange(wxFileDirPickerEvent& event) +{ + switch(event.GetId()) + { + case ID_MEMCARD1PATH: + LoadMemcard1(event.GetPath()); + break; + case ID_MEMCARD2PATH: + LoadMemcard2(event.GetPath()); + break; + default: + break; + } +} + +void CMemcardManager::OnRightClick(wxMouseEvent& event) +{ + // Focus the clicked item. + //int flags; + //long item = HitTest(event.GetPosition(), flags); + //if (item != wxNOT_FOUND) { + // SetItemState(item, wxLIST_STATE_SELECTED | wxLIST_STATE_FOCUSED, + // wxLIST_STATE_SELECTED | wxLIST_STATE_FOCUSED); + //} + + //int item = GetNextItem(-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED); + //if (item == -1) + //{ + // //not found + //} + //else + //{ + // //found + //} +} +void CMemcardManager::CopyClick(wxCommandEvent& WXUNUSED (event)) +{ + +} + +void CMemcardManager::DeleteClick(wxCommandEvent& WXUNUSED (event)) +{ + +} + +// These next two functions really need to be merged - yet +// retain ability to only (re)load one card at a time. +void CMemcardManager::LoadMemcard1(const char *card1) +{ + //wtf do these lines crash the app? + //if(memoryCard1) delete memoryCard1; + //if(memoryCard2) delete memoryCard2; + + // WARNING: the memcards don't have much error checking, yet! + if(card1 && strlen(card1)) + { + memoryCard1 = new GCMemcard(card1); + } + + if(memoryCard1) + { + m_Memcard1List->Hide(); + m_Memcard1List->ClearAll(); + m_Memcard1List->InsertColumn(COLUMN_FILENAME, _T("filename")); + m_Memcard1List->InsertColumn(COLUMN_COMMENT1, _T("comment1")); + m_Memcard1List->InsertColumn(COLUMN_COMMENT2, _T("comment2")); + + int nFiles = memoryCard1->GetNumFiles(); + for(int i=0;iGetFileName(i,fileName)) fileName[0]=0; + if(!memoryCard1->GetComment1(i,comment1)) comment1[0]=0; + if(!memoryCard1->GetComment2(i,comment2)) comment2[0]=0; + + // Add to list control + int index = m_Memcard1List->InsertItem(i, "row"); + m_Memcard1List->SetItem(index, 0, fileName); + m_Memcard1List->SetItem(index, 1, comment1); + m_Memcard1List->SetItem(index, 2, comment2); + } + m_Memcard1List->Show(); + } + else + { + m_Memcard2List->InsertColumn(COLUMN_FILENAME, _T("Error")); + + char tmp[128]; + sprintf(tmp, "Unable to load %s", card1); + long item = m_Memcard1List->InsertItem(0, tmp); + + m_Memcard1List->SetItemFont(item, *wxITALIC_FONT); + m_Memcard1List->SetColumnWidth(item, wxLIST_AUTOSIZE); + m_Memcard1List->SetItemState(0, wxLIST_STATE_SELECTED, wxLIST_STATE_SELECTED); + } + // automatic column width + for (int i = 0; i < m_Memcard1List->GetColumnCount(); i++) + { + m_Memcard1List->SetColumnWidth(i, wxLIST_AUTOSIZE); + } +} + +void CMemcardManager::LoadMemcard2(const char *card2) +{ + if(card2 && strlen(card2)) + { + memoryCard2 = new GCMemcard(card2); + } + + if(memoryCard2) + { + m_Memcard2List->Hide(); + m_Memcard2List->ClearAll(); + m_Memcard2List->InsertColumn(COLUMN_FILENAME, _T("filename")); + m_Memcard2List->InsertColumn(COLUMN_COMMENT1, _T("comment1")); + m_Memcard2List->InsertColumn(COLUMN_COMMENT2, _T("comment2")); + + int nFiles = memoryCard2->GetNumFiles(); + for(int i=0;iGetFileName(i,fileName)) fileName[0]=0; + if(!memoryCard2->GetComment1(i,comment1)) comment1[0]=0; + if(!memoryCard2->GetComment2(i,comment2)) comment2[0]=0; + + int index = m_Memcard2List->InsertItem(i, "row"); + m_Memcard2List->SetItem(index, 0, fileName); + m_Memcard2List->SetItem(index, 1, comment1); + m_Memcard2List->SetItem(index, 2, comment2); + } + m_Memcard2List->Show(); + } + else + { + m_Memcard2List->InsertColumn(COLUMN_FILENAME, _T("Error")); + + char tmp[128]; + sprintf(tmp, "Unable to load %s", card2); + long item = m_Memcard2List->InsertItem(0, tmp); + + m_Memcard2List->SetItemFont(item, *wxITALIC_FONT); + m_Memcard2List->SetColumnWidth(item, wxLIST_AUTOSIZE); + m_Memcard2List->SetItemState(0, wxLIST_STATE_SELECTED, wxLIST_STATE_SELECTED); + } + // automatic column width + for (int i = 0; i < m_Memcard2List->GetColumnCount(); i++) + { + m_Memcard2List->SetColumnWidth(i, wxLIST_AUTOSIZE); + } +} diff --git a/Source/Core/DolphinWX/src/MemcardManager.h b/Source/Core/DolphinWX/src/MemcardManager.h new file mode 100644 index 0000000000..cbf168640f --- /dev/null +++ b/Source/Core/DolphinWX/src/MemcardManager.h @@ -0,0 +1,91 @@ +// Copyright (C) 2003-2008 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + +#ifndef __MEMCARD_MANAGER_h__ +#define __MEMCARD_MANAGER_h__ + +#include +#include +#include +#include +#include + +#include "MemoryCards/GCMemcard.h" + +#undef MEMCARD_MANAGER_STYLE +#define MEMCARD_MANAGER_STYLE wxCAPTION | wxSYSTEM_MENU | wxDIALOG_NO_PARENT | wxCLOSE_BOX | wxRESIZE_BORDER + +class CMemcardManager + : public wxDialog +{ + public: + + CMemcardManager(wxWindow* parent, wxWindowID id = 1, const wxString& title = wxT("Memory Card Manager WARNING-In development, make backups first!"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = MEMCARD_MANAGER_STYLE); + virtual ~CMemcardManager(); + + private: + + DECLARE_EVENT_TABLE(); + + wxBoxSizer* sMain; + wxButton* m_CopyRight; + wxButton* m_CopyLeft; + wxButton* m_DeleteRight; + wxButton* m_DeleteLeft; + wxStaticBoxSizer* sMemcard1; + wxStaticBoxSizer* sMemcard2; + wxFilePickerCtrl* m_Memcard1Path; + wxFilePickerCtrl* m_Memcard2Path; + wxListCtrl* m_Memcard1List; + wxListCtrl* m_Memcard2List; + + enum + { + ID_COPYRIGHT = 1000, + ID_COPYLEFT = 1001, + ID_DELETERIGHT = 1002, + ID_DELETELEFT = 1003, + ID_MEMCARD1PATH = 1004, + ID_MEMCARD2PATH = 1005, + ID_MEMCARD1LIST = 1006, + ID_MEMCARD2LIST = 1007, + ID_DUMMY_VALUE_ //don't remove this value unless you have other enum values + }; + + enum + { + COLUMN_FILENAME = 0, + COLUMN_COMMENT1, + COLUMN_COMMENT2, + NUMBER_OF_COLUMN + }; + + GCMemcard *memoryCard1; + GCMemcard *memoryCard2; + + void LoadMemcard1(const char *card1); + void LoadMemcard2(const char *card2); + void OnPathChange(wxFileDirPickerEvent& event); + + void CreateGUIControls(); + void OnRightClick(wxMouseEvent& event); + void OnClose(wxCloseEvent& event); + void CopyClick(wxCommandEvent& event); + void DeleteClick(wxCommandEvent& event); +}; + +#endif diff --git a/Source/Core/DolphinWX/src/MemoryCards/GCMemcard.cpp b/Source/Core/DolphinWX/src/MemoryCards/GCMemcard.cpp new file mode 100644 index 0000000000..b374911c44 --- /dev/null +++ b/Source/Core/DolphinWX/src/MemoryCards/GCMemcard.cpp @@ -0,0 +1,394 @@ +// gcmc.cpp: define el punto de entrada de la aplicación de consola. +// + +#include "stdafx.h" +#include + +#include "GCMemcard.h" + +void GCMemcard::calc_checksumsBE(u16 *buf, u32 num, u16 *c1, u16 *c2) +{ + *c1 = 0;*c2 = 0; + for (u32 i = 0; i < num; ++i) + { + + *c1 += bswap16(buf[i]); + *c2 += bswap16((u16)(buf[i] ^ 0xffff)); + } + if (*c1 == 0xffff) + { + *c1 = 0; + } + if (*c2 == 0xffff) + { + *c2 = 0; + } +} + +u32 GCMemcard::GetNumFiles() +{ + if(!mcdFile) return 0; + + for(int i=0;i<127;i++) + { + if(BE32(dir.Dir[i].Gamecode)==0xFFFFFFFF) + return i; + } + return 127; +} + +bool GCMemcard::DeleteFile(u32 index) //index in the directory array +{ + if(!mcdFile) return false; + + //backup the directory and bat (not really needed here but meh :P + dir_backup=dir; + bat_backup=bat; + + int totalspace = (((u32)BE16(hdr.Size)*16)-5); + + //free the blocks + int blocks_left = BE16(dir.Dir[index].BlockCount); + int block = BE16(dir.Dir[index].FirstBlock); + do + { + int cbi = block-5; + int nextblock=bswap16(bat.Map[cbi]); + //assert(nextblock!=0); + if(nextblock==0) + { + nextblock = block+1; + } + + bat.Map[cbi]=0; + + block=nextblock; + blocks_left--; + } + while((block!=0xffff)&&(blocks_left>0)); + + //delete directory entry + for(int i=index;i<126;i++) + { + dir.Dir[i]=dir.Dir[i+1]; + } + memset(&(dir.Dir[126]),0xFF,sizeof(DEntry)); + + //pack blocks to remove free space partitioning, assume no fragmentation. + u8 *mc_data2 = new u8[mc_data_size]; + + int firstFree=0; + for(int i=0;i<127;i++) + { + if(BE32(dir.Dir[i].Gamecode)==0xFFFFFFFF) + { + break; + } + + int fb = BE16(dir.Dir[i].FirstBlock); + int bc = BE16(dir.Dir[i].BlockCount); + + u8* src = mc_data + (fb-5)*0x2000; + u8* dst = mc_data2 + firstFree*0x2000; + + memcpy(dst,src,bc*0x2000); + + for(int j=0;j>8); + dir.Dir[i].FirstBlock[1] = u8(firstFree); + + firstFree += bc; + } + + for(int j=firstFree;j>8); + bat.LastAllocated[1] = u8(firstFree); + + delete mc_data; + mc_data=mc_data2; + //-- + + //update freespace counter + int freespace1 = totalspace - firstFree; + bat.FreeBlocks[0] = u8(freespace1>>8); + bat.FreeBlocks[1] = u8(freespace1); + + //fix checksums + u16 csum1=0,csum2=0; + calc_checksumsBE((u16*)&dir,0xFFE,&csum1,&csum2); + dir.CheckSum1[0]=u8(csum1>>8); + dir.CheckSum1[1]=u8(csum1); + dir.CheckSum2[0]=u8(csum2>>8); + dir.CheckSum2[1]=u8(csum2); + calc_checksumsBE((u16*)(((u8*)&bat)+4),0xFFE,&csum1,&csum2); + bat.CheckSum1[0]=u8(csum1>>8); + bat.CheckSum1[1]=u8(csum1); + bat.CheckSum2[0]=u8(csum2>>8); + bat.CheckSum2[1]=u8(csum2); + + return true; +} + +u32 GCMemcard::ImportFile(DEntry& direntry, u8* contents) +{ + if(!mcdFile) return 0; + + if(BE16(bat.FreeBlocks) firstFree1) firstFree1 = firstFree2; + if(firstFree3 > firstFree1) firstFree1 = firstFree3; + + // find first free dir entry + int index=-1; + for(int i=0;i<127;i++) + { + if(BE32(dir.Dir[i].Gamecode)==0xFFFFFFFF) + { + index=i; + dir.Dir[i] = direntry; + dir.Dir[i].FirstBlock[0] = u8(firstFree1>>8); + dir.Dir[i].FirstBlock[1] = u8(firstFree1); + break; + } + } + + // keep assuming no freespace fragmentation, and copy over all the data + u8*destination = mc_data + (firstFree1-5)*0x2000; + + int fileBlocks=BE16(direntry.BlockCount); + memcpy(destination,contents,0x2000*fileBlocks); + + + //update freespace counter + int freespace1 = totalspace - firstFree1; + bat.FreeBlocks[0] = u8(freespace1>>8); + bat.FreeBlocks[1] = u8(freespace1); + + //fix checksums + u16 csum1=0,csum2=0; + calc_checksumsBE((u16*)&dir,0xFFE,&csum1,&csum2); + dir.CheckSum1[0]=u8(csum1>>8); + dir.CheckSum1[1]=u8(csum1); + dir.CheckSum2[0]=u8(csum2>>8); + dir.CheckSum2[1]=u8(csum2); + calc_checksumsBE((u16*)(((u8*)&bat)+4),0xFFE,&csum1,&csum2); + bat.CheckSum1[0]=u8(csum1>>8); + bat.CheckSum1[1]=u8(csum1); + bat.CheckSum2[0]=u8(csum2>>8); + bat.CheckSum2[1]=u8(csum2); + + return fileBlocks; +} + +bool GCMemcard::GetFileData(u32 index, u8*dest) //index in the directory array +{ + if(!mcdFile) return false; + + int block = BE16(dir.Dir[index].FirstBlock); + assert((block!=0xFFFF)&&(block>0)); + do + { + int nextblock=bswap16(bat.Map[block-5]); + assert(nextblock>0); + + memcpy(dest,mc_data + 0x2000*(block-5),0x2000); + dest+=0x2000; + + block=nextblock; + } + while(block!=0xffff); + + return true; +} + +u32 GCMemcard::GetFileSize(u32 index) //index in the directory array +{ + if(!mcdFile) return 0; + + return BE16(dir.Dir[index].BlockCount); +} + +bool GCMemcard::GetFileInfo(u32 index, GCMemcard::DEntry& info) //index in the directory array +{ + if(!mcdFile) return false; + + info = dir.Dir[index]; + return true; +} +bool GCMemcard::GetFileName(u32 index, char *fn) //index in the directory array +{ + if(!mcdFile) return false; + + memcpy(fn,(const char*)dir.Dir[index].Filename,32); + fn[31]=0; + return true; +} + +bool GCMemcard::GetComment1(u32 index, char *fn) //index in the directory array +{ + if(!mcdFile) return false; + + u32 Comment1 =BE32(dir.Dir[index].CommentsAddr); + u32 DataBlock =BE16(dir.Dir[index].FirstBlock)-5; + if(Comment1==0xFFFFFFFF) + { + fn[0]=0; + return false; + } + + memcpy(fn,mc_data +(DataBlock*0x2000) + Comment1,32); + fn[31]=0; + return true; +} + +bool GCMemcard::GetComment2(u32 index, char *fn) //index in the directory array +{ + if(!mcdFile) return false; + + u32 Comment1 =BE32(dir.Dir[index].CommentsAddr); + u32 Comment2 =Comment1+32; + u32 DataBlock =BE16(dir.Dir[index].FirstBlock)-5; + if(Comment1==0xFFFFFFFF) + { + fn[0]=0; + return false; + } + + memcpy(fn,mc_data +(DataBlock*0x2000) + Comment2,32); + fn[31]=0; + return true; +} + +u32 GCMemcard::TestChecksums() +{ + if(!mcdFile) return 0xFFFFFFFF; + + u16 csum1=0,csum2=0; + + calc_checksumsBE((u16*)&hdr, 0xFE ,&csum1,&csum2); + if(BE16(hdr.CheckSum1)!=csum1) return 1; + if(BE16(hdr.CheckSum2)!=csum2) return 1; + + calc_checksumsBE((u16*)&dir,0xFFE,&csum1,&csum2); + if(BE16(dir.CheckSum1)!=csum1) return 2; + if(BE16(dir.CheckSum2)!=csum2) return 2; + + calc_checksumsBE((u16*)&dir_backup,0xFFE,&csum1,&csum2); + if(BE16(dir_backup.CheckSum1)!=csum1) return 3; + if(BE16(dir_backup.CheckSum2)!=csum2) return 3; + + calc_checksumsBE((u16*)(((u8*)&bat)+4),0xFFE,&csum1,&csum2); + if(BE16(bat.CheckSum1)!=csum1) return 4; + if(BE16(bat.CheckSum2)!=csum2) return 4; + + calc_checksumsBE((u16*)(((u8*)&bat_backup)+4),0xFFE,&csum1,&csum2); + if(BE16(bat_backup.CheckSum1)!=csum1) return 5; + if(BE16(bat_backup.CheckSum2)!=csum2) return 5; + + return 0; +} + +u32 GCMemcard::CopyFrom(GCMemcard& source, u32 index) +{ + if(!mcdFile) return 0; + + DEntry d; + if(!source.GetFileInfo(index,d)) return 0; + + u8 *t = new u8[source.GetFileSize(index)*0x2000]; + + if(!source.GetFileData(index,t)) return 0; + u32 ret = ImportFile(d,t); + + delete t; + + return ret; +} + +bool GCMemcard::Save() +{ + if(!mcdFile) return false; + + FILE *mcd=(FILE*)mcdFile; + fseek(mcd,0,SEEK_SET); + fwrite(&hdr,1,0x2000,mcd); + fwrite(&dir,1,0x2000,mcd); + fwrite(&dir_backup,1,0x2000,mcd); + fwrite(&bat,1,0x2000,mcd); + fwrite(&bat_backup,1,0x2000,mcd); + fwrite(mc_data,1,mc_data_size,mcd); + return true; +} + +bool GCMemcard::IsOpen() +{ + return (mcdFile!=NULL); +} + +GCMemcard::GCMemcard(const char *filename) +{ + FILE *mcd=fopen(filename,"r+b"); + mcdFile=mcd; + if(!mcd) return; + + fseek(mcd,0x0000,SEEK_SET); + assert(fread(&hdr, 1,0x2000,mcd)==0x2000); + assert(fread(&dir, 1,0x2000,mcd)==0x2000); + assert(fread(&dir_backup,1,0x2000,mcd)==0x2000); + assert(fread(&bat, 1,0x2000,mcd)==0x2000); + assert(fread(&bat_backup,1,0x2000,mcd)==0x2000); + + fseek(mcd,0xa000,SEEK_SET); + + mc_data_size=(((u32)BE16(hdr.Size)*16)-5)*0x2000; + mc_data = new u8[mc_data_size]; + + u32 read = fread(mc_data,1,mc_data_size,mcd); + assert(mc_data_size==read); +} + +GCMemcard::~GCMemcard() +{ + fclose((FILE*)mcdFile); +} diff --git a/Source/Core/DolphinWX/src/MemoryCards/GCMemcard.h b/Source/Core/DolphinWX/src/MemoryCards/GCMemcard.h new file mode 100644 index 0000000000..fa6989e14e --- /dev/null +++ b/Source/Core/DolphinWX/src/MemoryCards/GCMemcard.h @@ -0,0 +1,159 @@ +#pragma once + +typedef unsigned char u8; +typedef unsigned short u16; +typedef unsigned int u32; + +u16 __inline bswap16(u16 s) +{ + return (s>>8) | (s<<8); +} + +u32 __inline bswap32(u32 s) +{ + return (u32)bswap16((u16)(s>>16)) | ((u32)bswap16((u16)s)<<16); +} + +#ifndef max +template +T __inline max(T a, T b) +{ + return (b>a)?b:a; +} +#endif + +#define BE16(x) (((x)[0]<<8) | (x)[1]) +#define BE32(x) (((x)[0]<<24) | ((x)[1]<<16) | ((x)[2]<<8) | (x)[3]) + +class GCMemcard +{ + void* mcdFile; + + u32 mc_data_size; + u8* mc_data; + + void calc_checksumsBE(u16 *buf, u32 num, u16 *c1, u16 *c2); + +public: + +#pragma pack(push,1) + struct OSTime { + u32 low; + u32 high; + }; + + struct Header { //Offset Size Description + u8 Unk[12]; //0x0000 12 ? + OSTime fmtTime; //0x000c 8 time of format (OSTime value) + u8 UID[12]; //0x0014 12 unique card id (?) + u8 Pad1[2]; //0x0020 2 padding zeroes + u8 Size[2]; //0x0022 2 size of memcard in Mbits + u8 Encoding[2]; //0x0024 2 encoding (ASCII or japanese) + u8 Unused1[468]; //0x0026 468 unused (0xff) + u8 UpdateCounter[2];//0x01fa 2 update Counter (?, probably unused) + u8 CheckSum1[2]; //0x01fc 2 Checksum 1 (?) + u8 CheckSum2[2]; //0x01fe 2 Checksum 2 (?) + u8 Unused2[7680]; //0x0200 0x1e00 unused (0xff) + } hdr; + + struct DEntry { + u8 Gamecode[4]; //0x00 0x04 Gamecode + u8 Markercode[2]; //0x04 0x02 Makercode + u8 Unused1; //0x06 0x01 reserved/unused (always 0xff, has no effect) + u8 BIFlags; //0x07 0x01 banner gfx format and icon animation (Image Key) + // bit(s) description + // 2 Icon Animation 0: forward 1: ping-pong + // 1 0: No Banner 1: Banner present + // 0 Banner Color 0: RGB5A3 1: CI8 + // + u8 Filename[32]; //0x08 0x20 filename + u8 ModTime[4]; //0x28 0x04 Time of file's last modification in seconds since 12am, January 1st, 2000 + u8 ImageOffset[4]; //0x2c 0x04 image data offset + u8 IconFmt[2]; //0x30 0x02 icon gfx format (2bits per icon) + // bits Description + // 00 no icon + // 01 CI8 with a shared color palette after the last frame + // 10 RGB5A3 + // 11 CI8 with a unique color palette after itself + // + u8 AnimSpeed[2]; //0x32 0x02 animation speed (2bits per icon) (*1) + // bits Description + // 00 no icon + // 01 Icon lasts for 4 frames + // 10 Icon lasts for 8 frames + // 11 Icon lasts for 12 frames + // + u8 Permissions; //0x34 0x01 file-permissions + // bit permission Description + // 4 no move File cannot be moved by the IPL + // 3 no copy File cannot be copied by the IPL + // 2 public Can be read by any game + // + u8 CopyCounter; //0x35 0x01 copy counter (*2) + u8 FirstBlock[2]; //0x36 0x02 block no of first block of file (0 == offset 0) + u8 BlockCount[2]; //0x38 0x02 file-length (number of blocks in file) + u8 Unused2[2]; //0x3a 0x02 reserved/unused (always 0xffff, has no effect) + u8 CommentsAddr[4]; //0x3c 0x04 Address of the two comments within the file data (*3) + }; + + struct Directory { + DEntry Dir[127]; //0x0000 Directory Entries (max 127) + u8 Padding[0x3a]; + u8 UpdateCounter[2];//0x1ffa 2 update Counter + u8 CheckSum1[2]; //0x1ffc 2 Checksum 1 + u8 CheckSum2[2]; //0x1ffe 2 Checksum 2 + } dir, dir_backup; + + struct BlockAlloc { + u8 CheckSum1[2]; //0x0000 2 Checksum 1 + u8 CheckSum2[2]; //0x0002 2 Checksum 2 + u8 UpdateCounter[2];//0x0004 2 update Counter + u8 FreeBlocks[2]; //0x0006 2 free Blocks + u8 LastAllocated[2];//0x0008 2 last allocated Block + u16 Map[0xFFB]; //0x000a 0x1ff8 Map of allocated Blocks + } bat,bat_backup; +#pragma pack(pop) + + // constructor + GCMemcard(const char* fileName); + + // destructor + ~GCMemcard(); + + bool IsOpen(); + + u32 TestChecksums(); + + // get number of file entries in the directory + u32 GetNumFiles(); + + // read directory entry + bool GetFileInfo(u32 index, DEntry& data); + + // buffer needs to be a char[32] or bigger + bool GetFileName(u32 index, char* buffer); + + // buffer needs to be a char[32] or bigger + bool GetComment1(u32 index, char* buffer); + + // buffer needs to be a char[32] or bigger + bool GetComment2(u32 index, char* buffer); + + // get file length un bytes + u32 GetFileSize(u32 index); + + // assumes there's enough space in buffer + bool GetFileData(u32 index, u8* buffer); + + // delete a file from the directory + bool DeleteFile(u32 index); + + // adds the file to the directory and copies its contents + u32 ImportFile(DEntry& direntry, u8* contents); + + // reads a save from another memcard, and imports the data into this memcard + u32 CopyFrom(GCMemcard& source, u32 index); + + bool Save(); + +}; diff --git a/Source/Core/DolphinWX/src/PluginOptions.cpp b/Source/Core/DolphinWX/src/PluginOptions.cpp index 5b9197286f..a5c6126ed4 100644 --- a/Source/Core/DolphinWX/src/PluginOptions.cpp +++ b/Source/Core/DolphinWX/src/PluginOptions.cpp @@ -57,100 +57,77 @@ CPluginOptions::~CPluginOptions() void CPluginOptions::CreateGUIControls() { - SetTitle(wxT("Plugin Selection")); - SetIcon(wxNullIcon); - SetSize(0, 8, 440, 295); - Center(); - const wxChar* font_name = 0; - int font_size = 8; -#ifdef _WIN32 - OSVERSIONINFOEX os; - os.dwOSVersionInfoSize = sizeof(os); - GetVersionEx((OSVERSIONINFO*)&os); - - if (os.dwMajorVersion >= 6) - { - font_name = wxT("Segoe UI"); - font_size = 9; - } - else - { - font_name = wxT("Tahoma"); - } - - // -#endif - - wxFont font(font_size, wxSWISS, wxNORMAL, wxNORMAL, false, font_name); - OK = new wxButton(this, ID_OK, wxT("OK"), wxPoint(188, 240), wxSize(73, 25), 0, wxDefaultValidator, wxT("OK")); - OK->SetFont(font); - - Cancel = new wxButton(this, ID_CANCEL, wxT("Cancel"), wxPoint(268, 240), wxSize(73, 25), 0, wxDefaultValidator, wxT("Cancel")); - Cancel->SetFont(font); - - Apply = new wxButton(this, ID_APPLY, wxT("Apply"), wxPoint(348, 240), wxSize(73, 25), 0, wxDefaultValidator, wxT("Apply")); - Apply->SetFont(font); + OK = new wxButton(this, ID_OK, wxT("OK"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator); + Cancel = new wxButton(this, ID_CANCEL, wxT("Cancel"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator); + Apply = new wxButton(this, ID_APPLY, wxT("Apply"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator); Apply->Disable(); - { - GraphicSelection = new wxChoice(this, ID_GRAPHIC_CB, wxPoint(88, 16), wxSize(333, 23), NULL, 0, wxDefaultValidator, wxT("GraphicSelection")); - GraphicSelection->SetFont(font); + GraphicSelection = new wxChoice(this, ID_GRAPHIC_CB, wxDefaultPosition, wxDefaultSize, NULL, 0, wxDefaultValidator); + GraphicAbout = new wxButton(this, ID_GRAPHIC_ABOUT, wxT("About..."), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator); + GraphicConfig = new wxButton(this, ID_GRAPHIC_CONFIG, wxT("Config..."), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator); + GraphicText = new wxStaticText(this, ID_GRAPHIC_TEXT, wxT("GFX:"), wxDefaultPosition, wxDefaultSize); - GraphicAbout = new wxButton(this, ID_GRAPHIC_ABOUT, wxT("About..."), wxPoint(168, 48), wxSize(73, 25), 0, wxDefaultValidator, wxT("GraphicAbout")); - GraphicAbout->SetFont(font); + FillChoiceBox(GraphicSelection, PLUGIN_TYPE_VIDEO, SConfig::GetInstance().m_LocalCoreStartupParameter.m_strVideoPlugin); - GraphicConfig = new wxButton(this, ID_GRAPHIC_CONFIG, wxT("Config..."), wxPoint(88, 48), wxSize(73, 25), 0, wxDefaultValidator, wxT("GraphicConfig")); - GraphicConfig->SetFont(font); + DSPSelection = new wxChoice(this, ID_DSP_CB, wxDefaultPosition, wxDefaultSize, NULL, 0, wxDefaultValidator); + DSPAbout = new wxButton(this, ID_DSP_ABOUT, wxT("About..."), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator); + DSPConfig = new wxButton(this, ID_DSP_CONFIG, wxT("Config..."), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator); + DSPText = new wxStaticText(this, ID_DSP_TEXT, wxT("DSP:"), wxDefaultPosition, wxDefaultSize); - WxStaticText1 = new wxStaticText(this, ID_WXSTATICTEXT1, wxT("Graphic"), wxPoint(16, 21), wxDefaultSize, 0, wxT("WxStaticText1")); - WxStaticText1->SetFont(font); + FillChoiceBox(DSPSelection, PLUGIN_TYPE_DSP, SConfig::GetInstance().m_LocalCoreStartupParameter.m_strDSPPlugin); - FillChoiceBox(GraphicSelection, PLUGIN_TYPE_VIDEO, SConfig::GetInstance().m_LocalCoreStartupParameter.m_strVideoPlugin); - } + PADSelection = new wxChoice(this, ID_PAD_CB, wxDefaultPosition, wxDefaultSize, NULL, 0, wxDefaultValidator); + PADAbout = new wxButton(this, ID_PAD_ABOUT, wxT("About..."), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator); + PADConfig = new wxButton(this, ID_PAD_CONFIG, wxT("Config..."), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator); + PADText = new wxStaticText(this, ID_PAD_TEXT, wxT("PAD:"), wxDefaultPosition, wxDefaultSize); - { - DSPSelection = new wxChoice(this, ID_DSP_CB, wxPoint(88, 88), wxSize(333, 23), NULL, 0, wxDefaultValidator, wxT("DSPSelection")); - DSPSelection->SetFont(font); + FillChoiceBox(PADSelection, PLUGIN_TYPE_PAD, SConfig::GetInstance().m_LocalCoreStartupParameter.m_strPadPlugin); + + wxGridBagSizer* sConfig; + sConfig = new wxGridBagSizer(0, 0); + sConfig->SetFlexibleDirection(wxBOTH); + sConfig->SetNonFlexibleGrowMode(wxFLEX_GROWMODE_SPECIFIED); + sConfig->Add(GraphicText, wxGBPosition(0, 0), wxGBSpan(2, 1), wxALIGN_CENTER_VERTICAL|wxALL, 5); + sConfig->Add(GraphicSelection, wxGBPosition(0, 1), wxGBSpan(1, 2), wxEXPAND|wxALL, 5); + sConfig->Add(GraphicConfig, wxGBPosition(0, 3), wxGBSpan(1, 1), wxALL, 5); + sConfig->Add(GraphicAbout, wxGBPosition(0, 4), wxGBSpan(1, 1), wxALL, 5); - DSPAbout = new wxButton(this, ID_DSP_ABOUT, wxT("About..."), wxPoint(168, 120), wxSize(73, 25), 0, wxDefaultValidator, wxT("DSPAbout")); - DSPAbout->SetFont(font); + sConfig->Add(DSPText, wxGBPosition(2, 0), wxGBSpan(2, 1), wxALIGN_CENTER_VERTICAL|wxALL, 5); + sConfig->Add(DSPSelection, wxGBPosition(2, 1), wxGBSpan(1, 2), wxEXPAND|wxALL, 5); + sConfig->Add(DSPConfig, wxGBPosition(2, 3), wxGBSpan(1, 1), wxALL, 5); + sConfig->Add(DSPAbout, wxGBPosition(2, 4), wxGBSpan(1, 1), wxALL, 5); - DSPConfig = new wxButton(this, ID_DSP_CONFIG, wxT("Config..."), wxPoint(88, 120), wxSize(73, 25), 0, wxDefaultValidator, wxT("DSPConfig")); - DSPConfig->SetFont(font); + sConfig->Add(PADText, wxGBPosition(4, 0), wxGBSpan(2, 1), wxALIGN_CENTER_VERTICAL|wxALL, 5); + sConfig->Add(PADSelection, wxGBPosition(4, 1), wxGBSpan(1, 2), wxEXPAND|wxALL, 5); + sConfig->Add(PADConfig, wxGBPosition(4, 3), wxGBSpan(1, 1), wxALL, 5); + sConfig->Add(PADAbout, wxGBPosition(4, 4), wxGBSpan(1, 1), wxALL, 5); + sConfig->Layout(); - WxStaticText2 = new wxStaticText(this, ID_WXSTATICTEXT2, wxT("DSP"), wxPoint(16, 93), wxDefaultSize, 0, wxT("WxStaticText2")); - WxStaticText2->SetFont(font); - - FillChoiceBox(DSPSelection, PLUGIN_TYPE_DSP, SConfig::GetInstance().m_LocalCoreStartupParameter.m_strDSPPlugin); - } - - { - PADSelection = new wxChoice(this, ID_PAD_CB, wxPoint(88, 160), wxSize(333, 23), NULL, 0, wxDefaultValidator, wxT("PADSelection")); - PADSelection->SetFont(font); - - PADAbout = new wxButton(this, ID_PAD_ABOUT, wxT("About..."), wxPoint(168, 192), wxSize(73, 25), 0, wxDefaultValidator, wxT("PADAbout")); - PADAbout->SetFont(font); - - PADConfig = new wxButton(this, ID_PAD_CONFIG, wxT("Config..."), wxPoint(88, 192), wxSize(73, 25), 0, wxDefaultValidator, wxT("PADConfig")); - PADConfig->SetFont(font); - - WxStaticText3 = new wxStaticText(this, ID_WXSTATICTEXT3, wxT("Pad"), wxPoint(16, 165), wxDefaultSize, 0, wxT("WxStaticText3")); - WxStaticText3->SetFont(font); - - FillChoiceBox(PADSelection, PLUGIN_TYPE_PAD, SConfig::GetInstance().m_LocalCoreStartupParameter.m_strPadPlugin); - } + wxBoxSizer* sButtons; + sButtons = new wxBoxSizer(wxHORIZONTAL); + sButtons->Add(0, 0, 1, wxEXPAND, 5); + sButtons->Add(OK, 0, wxALL, 5); + sButtons->Add(Cancel, 0, wxALL, 5); + sButtons->Add(Apply, 0, wxALL, 5); + + wxBoxSizer* sMain; + sMain = new wxBoxSizer(wxVERTICAL); + sMain->Add(sConfig, 1, wxEXPAND|wxALL, 5); + sMain->Add(sButtons, 0, wxEXPAND, 5); + + Center(); + this->SetSizer(sMain); + sMain->SetSizeHints(this); } -void -CPluginOptions::OnClose(wxCloseEvent& WXUNUSED (event)) +void CPluginOptions::OnClose(wxCloseEvent& WXUNUSED (event)) { Destroy(); } -void -CPluginOptions::OKClick(wxCommandEvent& event) +void CPluginOptions::OKClick(wxCommandEvent& event) { switch (event.GetId()) { @@ -170,15 +147,13 @@ CPluginOptions::OKClick(wxCommandEvent& event) } -void -CPluginOptions::OnSelectionChanged(wxCommandEvent& WXUNUSED (event)) +void CPluginOptions::OnSelectionChanged(wxCommandEvent& WXUNUSED (event)) { Apply->Enable(); } -void -CPluginOptions::OnAbout(wxCommandEvent& event) +void CPluginOptions::OnAbout(wxCommandEvent& event) { switch (event.GetId()) { @@ -197,8 +172,7 @@ CPluginOptions::OnAbout(wxCommandEvent& event) } -void -CPluginOptions::OnConfig(wxCommandEvent& event) +void CPluginOptions::OnConfig(wxCommandEvent& event) { switch (event.GetId()) { @@ -217,8 +191,7 @@ CPluginOptions::OnConfig(wxCommandEvent& event) } -void -CPluginOptions::FillChoiceBox(wxChoice* _pChoice, int _PluginType, const std::string& _SelectFilename) +void CPluginOptions::FillChoiceBox(wxChoice* _pChoice, int _PluginType, const std::string& _SelectFilename) { _pChoice->Clear(); @@ -246,8 +219,7 @@ CPluginOptions::FillChoiceBox(wxChoice* _pChoice, int _PluginType, const std::st } -void -CPluginOptions::CallConfig(wxChoice* _pChoice) +void CPluginOptions::CallConfig(wxChoice* _pChoice) { int Index = _pChoice->GetSelection(); @@ -263,8 +235,7 @@ CPluginOptions::CallConfig(wxChoice* _pChoice) } -void -CPluginOptions::CallAbout(wxChoice* _pChoice) +void CPluginOptions::CallAbout(wxChoice* _pChoice) { int Index = _pChoice->GetSelection(); @@ -280,8 +251,7 @@ CPluginOptions::CallAbout(wxChoice* _pChoice) } -void -CPluginOptions::DoApply() +void CPluginOptions::DoApply() { Apply->Disable(); @@ -293,8 +263,7 @@ CPluginOptions::DoApply() } -bool -CPluginOptions::GetFilename(wxChoice* _pChoice, std::string& _rFilename) +bool CPluginOptions::GetFilename(wxChoice* _pChoice, std::string& _rFilename) { _rFilename.clear(); @@ -312,4 +281,3 @@ CPluginOptions::GetFilename(wxChoice* _pChoice, std::string& _rFilename) return(false); } - diff --git a/Source/Core/DolphinWX/src/PluginOptions.h b/Source/Core/DolphinWX/src/PluginOptions.h index ea1eabc8ce..553727794a 100644 --- a/Source/Core/DolphinWX/src/PluginOptions.h +++ b/Source/Core/DolphinWX/src/PluginOptions.h @@ -18,6 +18,8 @@ #ifndef __PLUGIN_OPTIONS_h__ #define __PLUGIN_OPTIONS_h__ +#include + #undef PLUGIN_OPTIONS_STYLE #define PLUGIN_OPTIONS_STYLE wxCAPTION | wxSYSTEM_MENU | wxDIALOG_NO_PARENT | wxMINIMIZE_BOX | wxCLOSE_BOX @@ -30,7 +32,7 @@ class CPluginOptions public: - CPluginOptions(wxWindow* parent, wxWindowID id = 1, const wxString& title = wxT("Untitled1"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = PLUGIN_OPTIONS_STYLE); + CPluginOptions(wxWindow* parent, wxWindowID id = 1, const wxString& title = wxT("Plugin Selection"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = PLUGIN_OPTIONS_STYLE); virtual ~CPluginOptions(); void OKClick(wxCommandEvent& event); void OnSelectionChanged(wxCommandEvent& event); @@ -47,17 +49,17 @@ class CPluginOptions wxButton* OK; wxButton* Cancel; wxButton* Apply; - wxStaticText* WxStaticText3; + wxStaticText* PADText; wxButton* PADAbout; wxButton* PADConfig; wxChoice* PADSelection; wxButton* DSPAbout; wxButton* DSPConfig; - wxStaticText* WxStaticText2; + wxStaticText* DSPText; wxChoice* DSPSelection; wxButton* GraphicAbout; wxButton* GraphicConfig; - wxStaticText* WxStaticText1; + wxStaticText* GraphicText; wxChoice* GraphicSelection; ////GUI Control Declaration End @@ -73,17 +75,17 @@ class CPluginOptions ID_CANCEL = 1034, ID_APPLY = 1033, ID_OK = 1032, - ID_WXSTATICTEXT3 = 1031, + ID_PAD_TEXT = 1031, ID_PAD_ABOUT = 1030, ID_PAD_CONFIG = 1029, ID_PAD_CB = 1028, ID_DSP_ABOUT = 1027, ID_DSP_CONFIG = 1026, - ID_WXSTATICTEXT2 = 1025, + ID_DSP_TEXT = 1025, ID_DSP_CB = 1024, ID_GRAPHIC_ABOUT = 1007, ID_GRAPHIC_CONFIG = 1006, - ID_WXSTATICTEXT1 = 1005, + ID_GRAPHIC_TEXT = 1005, ID_GRAPHIC_CB = 1003, ////GUI Enum Control ID End ID_DUMMY_VALUE_ //don't remove this value unless you have other enum values