Added support for AGP. Original patch by GreyRogue.

This commit is contained in:
skidau 2015-01-20 23:41:46 +11:00
parent 18cee2dcc7
commit a7299a7fff
11 changed files with 410 additions and 37 deletions

View File

@ -91,6 +91,7 @@ set(SRCS ActionReplay.cpp
HW/EXI.cpp HW/EXI.cpp
HW/EXI_Device.cpp HW/EXI_Device.cpp
HW/EXI_DeviceAD16.cpp HW/EXI_DeviceAD16.cpp
HW/EXI_DeviceAGP.cpp
HW/EXI_DeviceAMBaseboard.cpp HW/EXI_DeviceAMBaseboard.cpp
HW/EXI_DeviceEthernet.cpp HW/EXI_DeviceEthernet.cpp
HW/EXI_DeviceGecko.cpp HW/EXI_DeviceGecko.cpp

View File

@ -329,6 +329,8 @@ void SConfig::SaveCoreSettings(IniFile& ini)
core->Set("Latency", m_LocalCoreStartupParameter.iLatency); core->Set("Latency", m_LocalCoreStartupParameter.iLatency);
core->Set("MemcardAPath", m_strMemoryCardA); core->Set("MemcardAPath", m_strMemoryCardA);
core->Set("MemcardBPath", m_strMemoryCardB); core->Set("MemcardBPath", m_strMemoryCardB);
core->Set("AgpCartAPath", m_strGbaCartA);
core->Set("AgpCartBPath", m_strGbaCartB);
core->Set("SlotA", m_EXIDevice[0]); core->Set("SlotA", m_EXIDevice[0]);
core->Set("SlotB", m_EXIDevice[1]); core->Set("SlotB", m_EXIDevice[1]);
core->Set("SerialPort1", m_EXIDevice[2]); core->Set("SerialPort1", m_EXIDevice[2]);
@ -559,6 +561,8 @@ void SConfig::LoadCoreSettings(IniFile& ini)
core->Get("Latency", &m_LocalCoreStartupParameter.iLatency, 2); core->Get("Latency", &m_LocalCoreStartupParameter.iLatency, 2);
core->Get("MemcardAPath", &m_strMemoryCardA); core->Get("MemcardAPath", &m_strMemoryCardA);
core->Get("MemcardBPath", &m_strMemoryCardB); core->Get("MemcardBPath", &m_strMemoryCardB);
core->Get("AgpCartAPath", &m_strGbaCartA);
core->Get("AgpCartBPath", &m_strGbaCartB);
core->Get("SlotA", (int*)&m_EXIDevice[0], EXIDEVICE_MEMORYCARD); core->Get("SlotA", (int*)&m_EXIDevice[0], EXIDEVICE_MEMORYCARD);
core->Get("SlotB", (int*)&m_EXIDevice[1], EXIDEVICE_NONE); core->Get("SlotB", (int*)&m_EXIDevice[1], EXIDEVICE_NONE);
core->Get("SerialPort1", (int*)&m_EXIDevice[2], EXIDEVICE_NONE); core->Get("SerialPort1", (int*)&m_EXIDevice[2], EXIDEVICE_NONE);

View File

@ -41,6 +41,8 @@ struct SConfig : NonCopyable
std::string m_strMemoryCardA; std::string m_strMemoryCardA;
std::string m_strMemoryCardB; std::string m_strMemoryCardB;
std::string m_strGbaCartA;
std::string m_strGbaCartB;
TEXIDevices m_EXIDevice[3]; TEXIDevices m_EXIDevice[3];
SIDevices m_SIDevice[4]; SIDevices m_SIDevice[4];
std::string m_bba_mac; std::string m_bba_mac;

View File

@ -122,6 +122,7 @@
<ClCompile Include="HW\EXI_Channel.cpp" /> <ClCompile Include="HW\EXI_Channel.cpp" />
<ClCompile Include="HW\EXI_Device.cpp" /> <ClCompile Include="HW\EXI_Device.cpp" />
<ClCompile Include="HW\EXI_DeviceAD16.cpp" /> <ClCompile Include="HW\EXI_DeviceAD16.cpp" />
<ClCompile Include="HW\EXI_DeviceAGP.cpp" />
<ClCompile Include="HW\EXI_DeviceAMBaseboard.cpp" /> <ClCompile Include="HW\EXI_DeviceAMBaseboard.cpp" />
<ClCompile Include="HW\EXI_DeviceEthernet.cpp" /> <ClCompile Include="HW\EXI_DeviceEthernet.cpp" />
<ClCompile Include="HW\EXI_DeviceGecko.cpp" /> <ClCompile Include="HW\EXI_DeviceGecko.cpp" />
@ -330,6 +331,7 @@
<ClInclude Include="HW\EXI_Channel.h" /> <ClInclude Include="HW\EXI_Channel.h" />
<ClInclude Include="HW\EXI_Device.h" /> <ClInclude Include="HW\EXI_Device.h" />
<ClInclude Include="HW\EXI_DeviceAD16.h" /> <ClInclude Include="HW\EXI_DeviceAD16.h" />
<ClInclude Include="HW\EXI_DeviceAGP.h" />
<ClInclude Include="HW\EXI_DeviceAMBaseboard.h" /> <ClInclude Include="HW\EXI_DeviceAMBaseboard.h" />
<ClInclude Include="HW\EXI_DeviceEthernet.h" /> <ClInclude Include="HW\EXI_DeviceEthernet.h" />
<ClInclude Include="HW\EXI_DeviceGecko.h" /> <ClInclude Include="HW\EXI_DeviceGecko.h" />

View File

@ -385,6 +385,9 @@
<ClCompile Include="HW\EXI_DeviceAD16.cpp"> <ClCompile Include="HW\EXI_DeviceAD16.cpp">
<Filter>HW %28Flipper/Hollywood%29\EXI - Expansion Interface</Filter> <Filter>HW %28Flipper/Hollywood%29\EXI - Expansion Interface</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="HW\EXI_DeviceAGP.cpp">
<Filter>HW %28Flipper/Hollywood%29\EXI - Expansion Interface</Filter>
</ClCompile>
<ClCompile Include="HW\EXI_DeviceAMBaseboard.cpp"> <ClCompile Include="HW\EXI_DeviceAMBaseboard.cpp">
<Filter>HW %28Flipper/Hollywood%29\EXI - Expansion Interface</Filter> <Filter>HW %28Flipper/Hollywood%29\EXI - Expansion Interface</Filter>
</ClCompile> </ClCompile>
@ -914,6 +917,9 @@
<ClInclude Include="HW\EXI_DeviceAD16.h"> <ClInclude Include="HW\EXI_DeviceAD16.h">
<Filter>HW %28Flipper/Hollywood%29\EXI - Expansion Interface</Filter> <Filter>HW %28Flipper/Hollywood%29\EXI - Expansion Interface</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="HW\EXI_DeviceAGP.h">
<Filter>HW %28Flipper/Hollywood%29\EXI - Expansion Interface</Filter>
</ClInclude>
<ClInclude Include="HW\EXI_DeviceAMBaseboard.h"> <ClInclude Include="HW\EXI_DeviceAMBaseboard.h">
<Filter>HW %28Flipper/Hollywood%29\EXI - Expansion Interface</Filter> <Filter>HW %28Flipper/Hollywood%29\EXI - Expansion Interface</Filter>
</ClInclude> </ClInclude>

View File

@ -7,6 +7,7 @@
#include "Core/Core.h" #include "Core/Core.h"
#include "Core/HW/EXI_Device.h" #include "Core/HW/EXI_Device.h"
#include "Core/HW/EXI_DeviceAD16.h" #include "Core/HW/EXI_DeviceAD16.h"
#include "Core/HW/EXI_DeviceAGP.h"
#include "Core/HW/EXI_DeviceAMBaseboard.h" #include "Core/HW/EXI_DeviceAMBaseboard.h"
#include "Core/HW/EXI_DeviceEthernet.h" #include "Core/HW/EXI_DeviceEthernet.h"
#include "Core/HW/EXI_DeviceGecko.h" #include "Core/HW/EXI_DeviceGecko.h"
@ -84,6 +85,7 @@ public:
u32 ImmRead (u32 size) override {INFO_LOG(EXPANSIONINTERFACE, "EXI DUMMY %s ImmRead", m_strName.c_str()); return 0;} u32 ImmRead (u32 size) override {INFO_LOG(EXPANSIONINTERFACE, "EXI DUMMY %s ImmRead", m_strName.c_str()); return 0;}
void DMAWrite(u32 addr, u32 size) override {INFO_LOG(EXPANSIONINTERFACE, "EXI DUMMY %s DMAWrite: %08x bytes, from %08x to device", m_strName.c_str(), size, addr);} void DMAWrite(u32 addr, u32 size) override {INFO_LOG(EXPANSIONINTERFACE, "EXI DUMMY %s DMAWrite: %08x bytes, from %08x to device", m_strName.c_str(), size, addr);}
void DMARead (u32 addr, u32 size) override {INFO_LOG(EXPANSIONINTERFACE, "EXI DUMMY %s DMARead: %08x bytes, from device to %08x", m_strName.c_str(), size, addr);} void DMARead (u32 addr, u32 size) override {INFO_LOG(EXPANSIONINTERFACE, "EXI DUMMY %s DMARead: %08x bytes, from device to %08x", m_strName.c_str(), size, addr);}
bool IsPresent() override { return true; }
}; };
@ -129,6 +131,10 @@ IEXIDevice* EXIDevice_Create(TEXIDevices device_type, const int channel_num)
result = new CEXIGecko(); result = new CEXIGecko();
break; break;
case EXIDEVICE_AGP:
result = new CEXIAgp(channel_num);
break;
case EXIDEVICE_NONE: case EXIDEVICE_NONE:
default: default:
result = new IEXIDevice(); result = new IEXIDevice();

View File

@ -19,6 +19,7 @@ enum TEXIDevices
EXIDEVICE_GECKO, EXIDEVICE_GECKO,
EXIDEVICE_MEMORYCARDFOLDER, // Only used when creating a device by EXIDevice_Create EXIDEVICE_MEMORYCARDFOLDER, // Only used when creating a device by EXIDevice_Create
// Converted to EXIDEVICE_MEMORYCARD internally // Converted to EXIDEVICE_MEMORYCARD internally
EXIDEVICE_AGP,
EXIDEVICE_NONE = (u8)-1 EXIDEVICE_NONE = (u8)-1
}; };

View File

@ -0,0 +1,253 @@
// Copyright 2013 Dolphin Emulator Project
// Licensed under GPLv2
// Refer to the license.txt file included.
#include "Common/FileUtil.h"
#include "Common/MemoryUtil.h"
#include "Common/StdMakeUnique.h"
#include "Core/ConfigManager.h"
#include "Core/Core.h"
#include "Core/HW/EXI_Device.h"
#include "Core/HW/EXI_DeviceAGP.h"
#include "Core/HW/Memmap.h"
CEXIAgp::CEXIAgp(int index) :
m_slot(index)
{
// Create the ROM
m_pHashArray = (u8*)AllocateMemoryPages(HASH_SIZE);
m_rom_size = 0;
LoadRom();
m_address = 0;
m_rom_hash_loaded = false;
}
CEXIAgp::~CEXIAgp()
{
m_pROM = nullptr;
m_pHashArray = nullptr;
}
void CEXIAgp::DoHash(u8* data, u32 size)
{
for (u32 it = 0; it < size; it++)
{
m_hash = m_hash ^ data[it];
m_hash = m_pHashArray[m_hash];
}
}
void CEXIAgp::LoadRom()
{
// Load whole ROM dump
std::string path;
std::string filename;
std::string ext;
std::string gbapath;
SplitPath(m_slot == 0 ? SConfig::GetInstance().m_strGbaCartA : SConfig::GetInstance().m_strGbaCartB, &path, &filename, &ext);
gbapath = path + filename;
LoadFileToROM(gbapath + ext);
INFO_LOG(EXPANSIONINTERFACE, "Loaded gba rom: %s card: %d", gbapath.c_str(), m_slot);
LoadFileToEEPROM(gbapath + ".sav");
INFO_LOG(EXPANSIONINTERFACE, "Loaded gba sav: %s card: %d", gbapath.c_str(), m_slot);
}
void CEXIAgp::LoadFileToROM(std::string filename)
{
File::IOFile pStream(filename, "rb");
if (pStream)
{
u64 filesize = pStream.GetSize();
m_rom_size = filesize & 0xFFFFFFFF;
m_rom_mask = (m_rom_size - 1);
m_pROM = (u8*)AllocateMemoryPages(m_rom_size);
pStream.ReadBytes(m_pROM, filesize);
}
else
{
// dummy rom data
m_pROM = (u8*)AllocateMemoryPages(0x2000);
}
}
void CEXIAgp::LoadFileToEEPROM(std::string filename)
{
File::IOFile pStream(filename, "rb");
if (pStream)
{
u64 filesize = pStream.GetSize();
m_eeprom_size = filesize & 0xFFFFFFFF;
m_eeprom_mask = (m_eeprom_size - 1);
m_pEEPROM = (u8*)AllocateMemoryPages(m_eeprom_size);
pStream.ReadBytes(m_pEEPROM, filesize);
}
}
void CEXIAgp::LoadHash()
{
if (!m_rom_hash_loaded && m_rom_size > 0)
{
for (int i = 0; i < 0x100; i++)
{
m_pHashArray[i] = Memory::ReadUnchecked_U8(0x0017e908 + i);
}
m_rom_hash_loaded = true;
}
}
u32 CEXIAgp::ImmRead(u32 _uSize)
{
// We don't really care about _uSize
(void)_uSize;
u32 uData = 0;
u8 RomVal1, RomVal2, RomVal3, RomVal4;
switch (m_currrent_cmd)
{
case 0xAE000000:
uData = 0x5AAA5517; // 17 is precalculated hash
m_currrent_cmd = 0;
break;
case 0xAE010000:
uData = (m_return_pos == 0) ? 0x01020304 : 0xF0020304; // F0 is precalculated hash, 020304 is left over
if (m_return_pos == 1)
m_currrent_cmd = 0;
else
m_return_pos = 1;
break;
case 0xAE020000:
if (m_rw_offset == 0x8000000)
{
RomVal1 = 0x0;
RomVal2 = 0x1;
}
else
{
RomVal1 = m_pROM[m_rw_offset++];
RomVal2 = m_pROM[m_rw_offset++];
LoadHash();
}
DoHash(&RomVal2, 1);
DoHash(&RomVal1, 1);
uData = (RomVal2 << 24) | (RomVal1 << 16) | (m_hash << 8);
m_currrent_cmd = 0;
break;
case 0xAE030000:
if (_uSize == 1)
{
uData = 0xFF000000;
m_currrent_cmd = 0;
}
else
{
RomVal1 = m_pROM[m_rw_offset++];
RomVal2 = m_pROM[m_rw_offset++];
RomVal3 = m_pROM[m_rw_offset++];
RomVal4 = m_pROM[m_rw_offset++];
LoadHash();
DoHash(&RomVal2, 1);
DoHash(&RomVal1, 1);
DoHash(&RomVal4, 1);
DoHash(&RomVal3, 1);
uData = (RomVal2 << 24) | (RomVal1 << 16) | (RomVal4 << 8) | (RomVal3);
}
break;
case 0xAE0B0000:
RomVal1 = m_eeprom_pos < 4 ? 0xA : (((u64*)m_pEEPROM)[(m_eeprom_cmd >> 1) & 0x3F] >> (m_eeprom_pos - 4)) & 0x1;
RomVal2 = 0;
DoHash(&RomVal2, 1);
DoHash(&RomVal1, 1);
uData = (RomVal2 << 24) | (RomVal1 << 16) | (m_hash << 8);
m_eeprom_pos++;
m_currrent_cmd = 0;
break;
case 0xAE0C0000:
uData = m_hash << 24;
m_currrent_cmd = 0;
break;
default:
uData = 0x0;
m_currrent_cmd = 0;
break;
}
INFO_LOG(EXPANSIONINTERFACE, "AGP read %x", uData);
return uData;
}
void CEXIAgp::ImmWrite(u32 _uData, u32 _uSize)
{
if ((_uSize == 1) && ((_uData & 0xFF000000) == 0))
return;
u8 HashCmd;
u64 Mask;
INFO_LOG(EXPANSIONINTERFACE, "AGP command %x", _uData);
switch (m_currrent_cmd)
{
case 0xAE020000:
case 0xAE030000:
m_rw_offset = ((_uData & 0xFFFFFF00) >> 7) & m_rom_mask;
m_return_pos = 0;
HashCmd = (_uData & 0xFF000000) >> 24;
DoHash(&HashCmd, 1);
HashCmd = (_uData & 0x00FF0000) >> 16;
DoHash(&HashCmd, 1);
HashCmd = (_uData & 0x0000FF00) >> 8;
DoHash(&HashCmd, 1);
break;
case 0xAE0C0000:
if ((m_eeprom_pos < 0x8) || (m_eeprom_pos == ((m_eeprom_cmd & EE_READ) ? 0x8 : 0x48)))
{
Mask = (u64)(1 << (0x8-(m_eeprom_pos > 0x8 ? 0x8 : m_eeprom_pos)));
if ((_uData >> 16) & 0x1)
m_eeprom_cmd |= Mask;
else
m_eeprom_cmd &= ~Mask;
if (m_eeprom_pos == 0x48)
((u64*)(m_pEEPROM))[(m_eeprom_cmd >> 1) & 0x3F] = m_eeprom_data;
}
else
{
Mask = (u64)(1 << (0x47 - m_eeprom_pos));
if ((_uData >> 16) & 0x1)
m_eeprom_data |= Mask;
else
m_eeprom_data &= ~Mask;
}
m_eeprom_pos++;
m_return_pos = 0;
HashCmd = (_uData & 0xFF000000) >> 24;
DoHash(&HashCmd, 1);
HashCmd = (_uData & 0x00FF0000) >> 16;
DoHash(&HashCmd, 1);
break;
case 0xAE0B0000:
break;
case 0xAE000000:
case 0xAE010000:
case 0xAE090000:
case 0xAE0A0000:
default:
m_eeprom_pos = 0;
m_currrent_cmd = _uData;
m_return_pos = 0;
m_hash = 0xFF;
HashCmd = (_uData & 0x00FF0000) >> 16;
DoHash(&HashCmd, 1);
break;
}
}
void CEXIAgp::DoState(PointerWrap &p)
{
p.Do(m_position);
p.Do(m_address);
p.Do(m_rw_offset);
p.Do(m_hash);
}

View File

@ -0,0 +1,61 @@
// Copyright 2013 Dolphin Emulator Project
// Licensed under GPLv2
// Refer to the license.txt file included.
#pragma once
#include <deque>
#include <queue>
#include "Core/HW/EXI_Device.h"
class CEXIAgp
: public IEXIDevice
{
public:
CEXIAgp(const int index);
virtual ~CEXIAgp() override;
bool IsPresent() override { return true; }
void ImmWrite(u32 _uData, u32 _uSize) override;
u32 ImmRead(u32 _uSize) override;
void DoState(PointerWrap &p) override;
private:
enum
{
HASH_SIZE = 256,
HASH_MASK = (HASH_SIZE - 1),
EE_READ = 0x80
};
int m_slot;
//! ROM
u32 m_rom_size = 0;
u32 m_rom_mask = 0;
u32 m_eeprom_size = 0;
u32 m_eeprom_mask = 0;
u8* m_pROM;
u8* m_pEEPROM;
u8* m_pHashArray;
//! Helper
u32 m_position = 0;
u32 m_address = 0;
u32 m_rw_offset = 0;
u64 m_eeprom_data = 0;
u8 m_eeprom_pos = 0;
u16 m_eeprom_cmd = 0;
void LoadFileToROM(std::string filename);
void LoadFileToEEPROM(std::string filename);
void LoadHash();
void LoadRom();
void DoHash(u8* data, u32 size);
u8 m_hash = 0;
u32 m_currrent_cmd = 0;
u32 m_return_pos = 0;
bool m_rom_hash_loaded = false;
};

View File

@ -111,6 +111,7 @@ static const wxLanguage langIds[] =
#define EXIDEV_MEMDIR_STR _trans("GCI Folder") #define EXIDEV_MEMDIR_STR _trans("GCI Folder")
#define EXIDEV_MIC_STR _trans("Mic") #define EXIDEV_MIC_STR _trans("Mic")
#define EXIDEV_BBA_STR "BBA" #define EXIDEV_BBA_STR "BBA"
#define EXIDEV_AGP_STR "Advance Game Port"
#define EXIDEV_AM_BB_STR _trans("AM-Baseboard") #define EXIDEV_AM_BB_STR _trans("AM-Baseboard")
#define EXIDEV_GECKO_STR "USBGecko" #define EXIDEV_GECKO_STR "USBGecko"
@ -382,8 +383,9 @@ void CConfigMain::InitializeGUIValues()
SlotDevices.Add(_(DEV_NONE_STR)); SlotDevices.Add(_(DEV_NONE_STR));
SlotDevices.Add(_(DEV_DUMMY_STR)); SlotDevices.Add(_(DEV_DUMMY_STR));
SlotDevices.Add(_(EXIDEV_MEMCARD_STR)); SlotDevices.Add(_(EXIDEV_MEMCARD_STR));
SlotDevices.Add(_(EXIDEV_GECKO_STR));
SlotDevices.Add(_(EXIDEV_MEMDIR_STR)); SlotDevices.Add(_(EXIDEV_MEMDIR_STR));
SlotDevices.Add(_(EXIDEV_GECKO_STR));
SlotDevices.Add(_(EXIDEV_AGP_STR));
#if HAVE_PORTAUDIO #if HAVE_PORTAUDIO
SlotDevices.Add(_(EXIDEV_MIC_STR)); SlotDevices.Add(_(EXIDEV_MIC_STR));
@ -415,10 +417,16 @@ void CConfigMain::InitializeGUIValues()
isMemcard = GCEXIDevice[i]->SetStringSelection(SlotDevices[2]); isMemcard = GCEXIDevice[i]->SetStringSelection(SlotDevices[2]);
break; break;
case EXIDEVICE_MEMORYCARDFOLDER: case EXIDEVICE_MEMORYCARDFOLDER:
GCEXIDevice[i]->SetStringSelection(SlotDevices[3]);
break;
case EXIDEVICE_GECKO:
GCEXIDevice[i]->SetStringSelection(SlotDevices[4]); GCEXIDevice[i]->SetStringSelection(SlotDevices[4]);
break; break;
case EXIDEVICE_AGP:
isMemcard = GCEXIDevice[i]->SetStringSelection(SlotDevices[5]);
break;
case EXIDEVICE_MIC: case EXIDEVICE_MIC:
GCEXIDevice[i]->SetStringSelection(SlotDevices[5]); GCEXIDevice[i]->SetStringSelection(SlotDevices[6]);
break; break;
case EXIDEVICE_ETH: case EXIDEVICE_ETH:
GCEXIDevice[i]->SetStringSelection(SP1Devices[2]); GCEXIDevice[i]->SetStringSelection(SP1Devices[2]);
@ -426,9 +434,6 @@ void CConfigMain::InitializeGUIValues()
case EXIDEVICE_AM_BASEBOARD: case EXIDEVICE_AM_BASEBOARD:
GCEXIDevice[i]->SetStringSelection(SP1Devices[3]); GCEXIDevice[i]->SetStringSelection(SP1Devices[3]);
break; break;
case EXIDEVICE_GECKO:
GCEXIDevice[i]->SetStringSelection(SlotDevices[3]);
break;
case EXIDEVICE_DUMMY: case EXIDEVICE_DUMMY:
default: default:
GCEXIDevice[i]->SetStringSelection(SlotDevices[1]); GCEXIDevice[i]->SetStringSelection(SlotDevices[1]);
@ -1015,68 +1020,98 @@ void CConfigMain::GCSettingsChanged(wxCommandEvent& event)
ChooseEXIDevice(event.GetString(), exidevice); ChooseEXIDevice(event.GetString(), exidevice);
break; break;
case ID_GC_EXIDEVICE_SLOTA_PATH: case ID_GC_EXIDEVICE_SLOTA_PATH:
ChooseMemcardPath(SConfig::GetInstance().m_strMemoryCardA, true); ChooseSlotPath(true, SConfig::GetInstance().m_EXIDevice[0]);
break; break;
case ID_GC_EXIDEVICE_SLOTB_PATH: case ID_GC_EXIDEVICE_SLOTB_PATH:
ChooseMemcardPath(SConfig::GetInstance().m_strMemoryCardB, false); ChooseSlotPath(false, SConfig::GetInstance().m_EXIDevice[0]);
break; break;
} }
} }
void CConfigMain::ChooseMemcardPath(std::string& strMemcard, bool isSlotA) void CConfigMain::ChooseSlotPath(bool isSlotA, TEXIDevices device_type)
{ {
bool memcard = (device_type == EXIDEVICE_MEMORYCARD);
std::string path;
std::string cardname;
std::string ext;
std::string pathA = SConfig::GetInstance().m_strMemoryCardA;
std::string pathB = SConfig::GetInstance().m_strMemoryCardB;
if (!memcard)
{
pathA = SConfig::GetInstance().m_strGbaCartA;
pathB = SConfig::GetInstance().m_strGbaCartB;
}
SplitPath(isSlotA ? pathA : pathB, &path, &cardname, &ext);
std::string filename = WxStrToStr(wxFileSelector( std::string filename = WxStrToStr(wxFileSelector(
_("Choose a file to open"), _("Choose a file to open"),
StrToWxStr(File::GetUserPath(D_GCUSER_IDX)), StrToWxStr(path),
isSlotA ? GC_MEMCARDA : GC_MEMCARDB, StrToWxStr(cardname),
wxEmptyString, StrToWxStr(ext),
_("GameCube Memory Cards (*.raw,*.gcp)") + "|*.raw;*.gcp")); memcard ? _("GameCube Memory Cards (*.raw,*.gcp)") + "|*.raw;*.gcp" : _("Game Boy Advance Carts (*.gba)") + "|*.gba"));
if (!filename.empty()) if (!filename.empty())
{ {
if (File::Exists(filename)) if (File::Exists(filename))
{ {
GCMemcard memorycard(filename); if (memcard)
if (!memorycard.IsValid()) {
GCMemcard memorycard(filename);
if (!memorycard.IsValid())
{
WxUtils::ShowErrorDialog(wxString::Format(_("Cannot use that file as a memory card.\n%s\n" \
"is not a valid gamecube memory card file"), filename.c_str()));
return;
}
}
else
{ {
WxUtils::ShowErrorDialog(wxString::Format(_("Cannot use that file as a memory card.\n%s\n" \
"is not a valid gamecube memory card file"), filename.c_str()));
return; return;
} }
} }
#ifdef _WIN32 #ifdef _WIN32
if (!strncmp(File::GetExeDirectory().c_str(), filename.c_str(), File::GetExeDirectory().size())) if (!strncmp(File::GetExeDirectory().c_str(), filename.c_str(), File::GetExeDirectory().size()))
{
// If the Exe Directory Matches the prefix of the filename, we still need to verify
// that the next character is a directory separator character, otherwise we may create an invalid path
char next_char = filename.at(File::GetExeDirectory().size()) + 1;
if (next_char == '/' || next_char == '\\')
{ {
// If the Exe Directory Matches the prefix of the filename, we still need to verify filename.erase(0, File::GetExeDirectory().size() + 1);
// that the next character is a directory separator character, otherwise we may create an invalid path filename = "./" + filename;
char next_char = filename.at(File::GetExeDirectory().size())+1;
if (next_char == '/' || next_char == '\\')
{
filename.erase(0, File::GetExeDirectory().size() +1);
filename = "./" + filename;
}
} }
#endif }
#endif
// also check that the path isn't used for the other memcard... // also check that the path isn't used for the other memcard...
if (filename.compare(isSlotA ? SConfig::GetInstance().m_strMemoryCardB if (filename.compare(isSlotA ? pathB : pathA) != 0)
: SConfig::GetInstance().m_strMemoryCardA) != 0)
{ {
strMemcard = filename; if (memcard)
{
if (isSlotA)
SConfig::GetInstance().m_strMemoryCardA = filename;
else
SConfig::GetInstance().m_strMemoryCardB = filename;
}
else
{
if (isSlotA)
SConfig::GetInstance().m_strGbaCartA = filename;
else
SConfig::GetInstance().m_strGbaCartB = filename;
}
if (Core::IsRunning()) if (Core::IsRunning())
{ {
// Change memcard to the new file // Change memcard to the new file
ExpansionInterface::ChangeDevice( ExpansionInterface::ChangeDevice(
isSlotA ? 0 : 1, // SlotA: channel 0, SlotB channel 1 isSlotA ? 0 : 1, // SlotA: channel 0, SlotB channel 1
EXIDEVICE_MEMORYCARD, device_type,
0); // SP1 is device 2, slots are device 0 0); // SP1 is device 2, slots are device 0
} }
} }
else else
{ {
WxUtils::ShowErrorDialog(_("Cannot use that file as a memory card.\n" WxUtils::ShowErrorDialog(_("Are you trying to use the same file in both slots?"));
"Are you trying to use the same file in both slots?"));
} }
} }
} }
@ -1093,6 +1128,8 @@ void CConfigMain::ChooseEXIDevice(wxString deviceName, int deviceNum)
tempType = EXIDEVICE_MIC; tempType = EXIDEVICE_MIC;
else if (!deviceName.compare(EXIDEV_BBA_STR)) else if (!deviceName.compare(EXIDEV_BBA_STR))
tempType = EXIDEVICE_ETH; tempType = EXIDEVICE_ETH;
else if (!deviceName.compare(EXIDEV_AGP_STR))
tempType = EXIDEVICE_AGP;
else if (!deviceName.compare(_(EXIDEV_AM_BB_STR))) else if (!deviceName.compare(_(EXIDEV_AM_BB_STR)))
tempType = EXIDEVICE_AM_BASEBOARD; tempType = EXIDEVICE_AM_BASEBOARD;
else if (!deviceName.compare(EXIDEV_GECKO_STR)) else if (!deviceName.compare(EXIDEV_GECKO_STR))
@ -1102,8 +1139,8 @@ void CConfigMain::ChooseEXIDevice(wxString deviceName, int deviceNum)
else else
tempType = EXIDEVICE_DUMMY; tempType = EXIDEVICE_DUMMY;
// Gray out the memcard path button if we're not on a memcard // Gray out the memcard path button if we're not on a memcard or AGP
if (tempType == EXIDEVICE_MEMORYCARD) if (tempType == EXIDEVICE_MEMORYCARD || tempType == EXIDEVICE_AGP)
GCMemcardPath[deviceNum]->Enable(); GCMemcardPath[deviceNum]->Enable();
else if (deviceNum == 0 || deviceNum == 1) else if (deviceNum == 0 || deviceNum == 1)
GCMemcardPath[deviceNum]->Disable(); GCMemcardPath[deviceNum]->Disable();

View File

@ -254,7 +254,7 @@ private:
void AddAudioBackends(); void AddAudioBackends();
void GCSettingsChanged(wxCommandEvent& event); void GCSettingsChanged(wxCommandEvent& event);
void ChooseMemcardPath(std::string& strMemcard, bool isSlotA); void ChooseSlotPath(bool isSlotA, TEXIDevices device_type);
void ChooseEXIDevice(wxString deviceName, int deviceNum); void ChooseEXIDevice(wxString deviceName, int deviceNum);
void WiiSettingsChanged(wxCommandEvent& event); void WiiSettingsChanged(wxCommandEvent& event);