1
0
mirror of https://github.com/dolphin-emu/dolphin synced 2024-07-08 20:25:52 +00:00

Remove AM Baseboard

Let's stop pretending that we support Triforce emulation.
Keeping this code around just in case someone will make
major improvements in the future isn't really worth it.

I'm keeping the Triforce game INIs so users will know that
the compatibility rating for Triforce games is 1 star (broken).
This commit is contained in:
JosJuice 2016-08-10 19:23:21 +02:00
parent 088f7eaa3d
commit 3bb0e7e3f5
17 changed files with 28 additions and 905 deletions

View File

@ -1026,7 +1026,7 @@ set(CPACK_PACKAGE_VERSION_MAJOR ${DOLPHIN_VERSION_MAJOR})
set(CPACK_PACKAGE_VERSION_MINOR ${DOLPHIN_VERSION_MINOR})
set(CPACK_PACKAGE_VERSION_PATCH ${DOLPHIN_VERSION_PATCH})
set(CPACK_PACKAGE_DESCRIPTION_FILE ${PROJECT_SOURCE_DIR}/Data/cpack_package_description.txt)
set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "A GameCube, Wii and Triforce emulator")
set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "A GameCube and Wii emulator")
set(CPACK_RPM_PACKAGE_GROUP System/Emulators/Other)
set(CPACK_RPM_PACKAGE_LICENSE GPL-2.0)

View File

@ -1,10 +1,10 @@
# Dolphin - A GameCube / Wii / Triforce Emulator
# Dolphin - A GameCube / Wii Emulator
[Homepage](https://dolphin-emu.org/) | [Project Site](https://github.com/dolphin-emu/dolphin) | [Forums](https://forums.dolphin-emu.org/) | [Wiki](https://wiki.dolphin-emu.org/) | [Issue Tracker](https://bugs.dolphin-emu.org/projects/emulator/issues) | [Coding Style](https://github.com/dolphin-emu/dolphin/blob/master/Contributing.md) | [Transifex Page](https://www.transifex.com/projects/p/dolphin-emu/)
Dolphin is an emulator for running GameCube, Wii, and Triforce games on
Windows, Linux, OS X, and recent Android devices. It's licensed under
the terms of the GNU General Public License, version 2 or later (GPLv2+).
Dolphin is an emulator for running GameCube and Wii games on Windows,
Linux, OS X, and recent Android devices. It's licensed under the terms
of the GNU General Public License, version 2 or later (GPLv2+).
Please read the [FAQ](https://dolphin-emu.org/docs/faq/) before using Dolphin.

View File

@ -90,7 +90,6 @@ set(SRCS ActionReplay.cpp
HW/EXI_Device.cpp
HW/EXI_DeviceAD16.cpp
HW/EXI_DeviceAGP.cpp
HW/EXI_DeviceAMBaseboard.cpp
HW/EXI_DeviceEthernet.cpp
HW/EXI_DeviceGecko.cpp
HW/EXI_DeviceIPL.cpp
@ -110,7 +109,6 @@ set(SRCS ActionReplay.cpp
HW/MMIO.cpp
HW/ProcessorInterface.cpp
HW/SI.cpp
HW/SI_DeviceAMBaseboard.cpp
HW/SI_Device.cpp
HW/SI_DeviceDanceMat.cpp
HW/SI_DeviceGBA.cpp

View File

@ -122,7 +122,6 @@
<ClCompile Include="HW\EXI_Device.cpp" />
<ClCompile Include="HW\EXI_DeviceAD16.cpp" />
<ClCompile Include="HW\EXI_DeviceAGP.cpp" />
<ClCompile Include="HW\EXI_DeviceAMBaseboard.cpp" />
<ClCompile Include="HW\EXI_DeviceEthernet.cpp" />
<ClCompile Include="HW\EXI_DeviceGecko.cpp" />
<ClCompile Include="HW\EXI_DeviceIPL.cpp" />
@ -143,7 +142,6 @@
<ClCompile Include="HW\ProcessorInterface.cpp" />
<ClCompile Include="HW\SI.cpp" />
<ClCompile Include="HW\SI_Device.cpp" />
<ClCompile Include="HW\SI_DeviceAMBaseboard.cpp" />
<ClCompile Include="HW\SI_DeviceDanceMat.cpp" />
<ClCompile Include="HW\SI_DeviceGBA.cpp" />
<ClCompile Include="HW\SI_DeviceGCAdapter.cpp" />
@ -328,7 +326,6 @@
<ClInclude Include="HW\EXI_Device.h" />
<ClInclude Include="HW\EXI_DeviceAD16.h" />
<ClInclude Include="HW\EXI_DeviceAGP.h" />
<ClInclude Include="HW\EXI_DeviceAMBaseboard.h" />
<ClInclude Include="HW\EXI_DeviceEthernet.h" />
<ClInclude Include="HW\EXI_DeviceGecko.h" />
<ClInclude Include="HW\EXI_DeviceIPL.h" />
@ -350,7 +347,6 @@
<ClInclude Include="HW\ProcessorInterface.h" />
<ClInclude Include="HW\SI.h" />
<ClInclude Include="HW\SI_Device.h" />
<ClInclude Include="HW\SI_DeviceAMBaseboard.h" />
<ClInclude Include="HW\SI_DeviceDanceMat.h" />
<ClInclude Include="HW\SI_DeviceGBA.h" />
<ClInclude Include="HW\SI_DeviceGCAdapter.h" />

View File

@ -384,9 +384,6 @@
<ClCompile Include="HW\EXI_DeviceAGP.cpp">
<Filter>HW %28Flipper/Hollywood%29\EXI - Expansion Interface</Filter>
</ClCompile>
<ClCompile Include="HW\EXI_DeviceAMBaseboard.cpp">
<Filter>HW %28Flipper/Hollywood%29\EXI - Expansion Interface</Filter>
</ClCompile>
<ClCompile Include="HW\EXI_DeviceEthernet.cpp">
<Filter>HW %28Flipper/Hollywood%29\EXI - Expansion Interface</Filter>
</ClCompile>
@ -438,9 +435,6 @@
<ClCompile Include="HW\SI_Device.cpp">
<Filter>HW %28Flipper/Hollywood%29\SI - Serial Interface</Filter>
</ClCompile>
<ClCompile Include="HW\SI_DeviceAMBaseboard.cpp">
<Filter>HW %28Flipper/Hollywood%29\SI - Serial Interface</Filter>
</ClCompile>
<ClCompile Include="HW\SI_DeviceDanceMat.cpp">
<Filter>HW %28Flipper/Hollywood%29\SI - Serial Interface</Filter>
</ClCompile>
@ -929,9 +923,6 @@
<ClInclude Include="HW\EXI_DeviceAGP.h">
<Filter>HW %28Flipper/Hollywood%29\EXI - Expansion Interface</Filter>
</ClInclude>
<ClInclude Include="HW\EXI_DeviceAMBaseboard.h">
<Filter>HW %28Flipper/Hollywood%29\EXI - Expansion Interface</Filter>
</ClInclude>
<ClInclude Include="HW\EXI_DeviceEthernet.h">
<Filter>HW %28Flipper/Hollywood%29\EXI - Expansion Interface</Filter>
</ClInclude>
@ -983,9 +974,6 @@
<ClInclude Include="HW\SI_Device.h">
<Filter>HW %28Flipper/Hollywood%29\SI - Serial Interface</Filter>
</ClInclude>
<ClInclude Include="HW\SI_DeviceAMBaseboard.h">
<Filter>HW %28Flipper/Hollywood%29\SI - Serial Interface</Filter>
</ClInclude>
<ClInclude Include="HW\SI_DeviceDanceMat.h">
<Filter>HW %28Flipper/Hollywood%29\SI - Serial Interface</Filter>
</ClInclude>

View File

@ -681,44 +681,23 @@ void ExecuteCommand(u32 command_0, u32 command_1, u32 command_2, u32 output_addr
u64 ticks_until_completion = SystemTimers::GetTicksPerSecond() / 15000;
bool command_handled_by_thread = false;
bool GCAM = (SConfig::GetInstance().m_SIDevice[0] == SIDEVICE_AM_BASEBOARD) &&
(SConfig::GetInstance().m_EXIDevice[2] == EXIDEVICE_AM_BASEBOARD);
// DVDLowRequestError needs access to the error code set by the previous command
if (command_0 >> 24 != DVDLowRequestError)
s_error_code = 0;
if (GCAM)
{
ERROR_LOG(DVDINTERFACE, "DVD: %08x, %08x, %08x, DMA=addr:%08x,len:%08x,ctrl:%08x", command_0,
command_1, command_2, output_address, output_length, s_DICR.Hex);
// decrypt command. But we have a zero key, that simplifies things a lot.
// If you get crazy dvd command errors, make sure 0x80000000 - 0x8000000c is zero'd
command_0 <<= 24;
}
switch (command_0 >> 24)
{
// Seems to be used by both GC and Wii
case DVDLowInquiry:
if (GCAM)
{
// 0x29484100...
// was 21 i'm not entirely sure about this, but it works well.
WriteImmediate(0x21000000, output_address, reply_to_ios);
}
else
{
// (shuffle2) Taken from my Wii
Memory::Write_U32(0x00000002, output_address);
Memory::Write_U32(0x20060526, output_address + 4);
// This was in the oubuf even though this cmd is only supposed to reply with 64bits
// However, this and other tests strongly suggest that the buffer is static, and it's never -
// or rarely cleared.
Memory::Write_U32(0x41000000, output_address + 8);
// (shuffle2) Taken from my Wii
Memory::Write_U32(0x00000002, output_address);
Memory::Write_U32(0x20060526, output_address + 4);
// This was in the oubuf even though this cmd is only supposed to reply with 64bits
// However, this and other tests strongly suggest that the buffer is static, and it's never -
// or rarely cleared.
Memory::Write_U32(0x41000000, output_address + 8);
INFO_LOG(DVDINTERFACE, "DVDLowInquiry (Buffer 0x%08x, 0x%x)", output_address, output_length);
}
INFO_LOG(DVDINTERFACE, "DVDLowInquiry (Buffer 0x%08x, 0x%x)", output_address, output_length);
break;
// Only seems to be used from WII_IPC, not through direct access
@ -865,56 +844,6 @@ void ExecuteCommand(u32 command_0, u32 command_1, u32 command_2, u32 output_addr
", DMABuffer = %08x, SrcLength = %08x, DMALength = %08x",
iDVDOffset, output_address, command_2, output_length);
if (GCAM)
{
if (iDVDOffset & 0x80000000) // read request to hardware buffer
{
switch (iDVDOffset)
{
case 0x80000000:
ERROR_LOG(DVDINTERFACE, "GC-AM: READ MEDIA BOARD STATUS (80000000)");
for (u32 i = 0; i < output_length; i += 4)
Memory::Write_U32(0, output_address + i);
break;
case 0x80000040:
ERROR_LOG(DVDINTERFACE, "GC-AM: READ MEDIA BOARD STATUS (2) (80000040)");
for (u32 i = 0; i < output_length; i += 4)
Memory::Write_U32(~0, output_address + i);
Memory::Write_U32(0x00000020, output_address); // DIMM SIZE, LE
Memory::Write_U32(0x4743414D, output_address + 4); // GCAM signature
break;
case 0x80000120:
ERROR_LOG(DVDINTERFACE, "GC-AM: READ FIRMWARE STATUS (80000120)");
for (u32 i = 0; i < output_length; i += 4)
Memory::Write_U32(0x01010101, output_address + i);
break;
case 0x80000140:
ERROR_LOG(DVDINTERFACE, "GC-AM: READ FIRMWARE STATUS (80000140)");
for (u32 i = 0; i < output_length; i += 4)
Memory::Write_U32(0x01010101, output_address + i);
break;
case 0x84000020:
ERROR_LOG(DVDINTERFACE, "GC-AM: READ MEDIA BOARD STATUS (1) (84000020)");
for (u32 i = 0; i < output_length; i += 4)
Memory::Write_U32(0x00000000, output_address + i);
break;
default:
ERROR_LOG(DVDINTERFACE, "GC-AM: UNKNOWN MEDIA BOARD LOCATION %" PRIx64, iDVDOffset);
break;
}
break;
}
else if ((iDVDOffset == 0x1f900000) || (iDVDOffset == 0x1f900020))
{
ERROR_LOG(DVDINTERFACE, "GC-AM: READ MEDIA BOARD COMM AREA (1f900020)");
u8* source = s_media_buffer + iDVDOffset - 0x1f900000;
Memory::CopyToEmu(output_address, source, output_length);
for (u32 i = 0; i < output_length; i += 4)
ERROR_LOG(DVDINTERFACE, "GC-AM: %08x", Memory::Read_U32(output_address + i));
break;
}
}
command_handled_by_thread =
ExecuteReadCommand(iDVDOffset, output_address, command_2, output_length, false,
reply_to_ios, &interrupt_type, &ticks_until_completion);
@ -934,138 +863,10 @@ void ExecuteCommand(u32 command_0, u32 command_1, u32 command_2, u32 output_addr
}
break;
// GC-AM only
case 0xAA:
if (GCAM)
{
ERROR_LOG(DVDINTERFACE, "GC-AM: 0xAA, DMABuffer=%08x, DMALength=%08x", output_address,
output_length);
u64 iDVDOffset = (u64)command_1 << 2;
u32 len = output_length;
s64 offset = iDVDOffset - 0x1F900000;
/*
if (iDVDOffset == 0x84800000)
{
ERROR_LOG(DVDINTERFACE, "Firmware upload");
}
else*/
if ((offset < 0) || ((offset + len) > 0x40) || len > 0x40)
{
u32 addr = output_address;
if (iDVDOffset == 0x84800000)
{
ERROR_LOG(DVDINTERFACE, "FIRMWARE UPLOAD");
}
else
{
ERROR_LOG(DVDINTERFACE, "ILLEGAL MEDIA WRITE");
}
while (len >= 4)
{
ERROR_LOG(DVDINTERFACE, "GC-AM Media Board WRITE (0xAA): %08" PRIx64 ": %08x", iDVDOffset,
Memory::Read_U32(addr));
addr += 4;
len -= 4;
iDVDOffset += 4;
}
}
else
{
u32 addr = s_DIMAR.Address;
Memory::CopyFromEmu(s_media_buffer + offset, addr, len);
while (len >= 4)
{
ERROR_LOG(DVDINTERFACE, "GC-AM Media Board WRITE (0xAA): %08" PRIx64 ": %08x", iDVDOffset,
Memory::Read_U32(addr));
addr += 4;
len -= 4;
iDVDOffset += 4;
}
}
}
break;
// Seems to be used by both GC and Wii
case DVDLowSeek:
if (!GCAM)
{
// Currently unimplemented
INFO_LOG(DVDINTERFACE, "Seek: offset=%09" PRIx64 " (ignoring)", (u64)command_1 << 2);
}
else
{
memset(s_media_buffer, 0, 0x20);
s_media_buffer[0] = s_media_buffer[0x20]; // ID
s_media_buffer[2] = s_media_buffer[0x22];
s_media_buffer[3] = s_media_buffer[0x23] | 0x80;
int cmd = (s_media_buffer[0x23] << 8) | s_media_buffer[0x22];
ERROR_LOG(DVDINTERFACE, "GC-AM: execute buffer, cmd=%04x", cmd);
switch (cmd)
{
case 0x00:
s_media_buffer[4] = 1;
break;
case 0x1:
s_media_buffer[7] = 0x20; // DIMM Size
break;
case 0x100:
{
// urgh
static int percentage = 0;
static int status = 0;
percentage++;
if (percentage > 100)
{
status++;
percentage = 0;
}
s_media_buffer[4] = status;
/* status:
0 - "Initializing media board. Please wait.."
1 - "Checking network. Please wait..."
2 - "Found a system disc. Insert a game disc"
3 - "Testing a game program. %d%%"
4 - "Loading a game program. %d%%"
5 - go
6 - error xx
*/
s_media_buffer[8] = percentage;
s_media_buffer[4] = 0x05;
s_media_buffer[8] = 0x64;
break;
}
case 0x101:
s_media_buffer[4] = 3; // version
s_media_buffer[5] = 3;
s_media_buffer[6] = 1; // xxx
s_media_buffer[8] = 1;
s_media_buffer[16] = 0xFF;
s_media_buffer[17] = 0xFF;
s_media_buffer[18] = 0xFF;
s_media_buffer[19] = 0xFF;
break;
case 0x102: // get error code
s_media_buffer[4] = 1; // 0: download incomplete (31), 1: corrupted, other error 1
s_media_buffer[5] = 0;
break;
case 0x103:
memcpy(s_media_buffer + 4, "A89E27A50364511", 15); // serial
break;
#if 0
case 0x301: // unknown
memcpy(s_media_buffer + 4, s_media_buffer + 0x24, 0x1c);
break;
case 0x302:
break;
#endif
default:
ERROR_LOG(DVDINTERFACE, "GC-AM: execute buffer (unknown)");
break;
}
memset(s_media_buffer + 0x20, 0, 0x20);
WriteImmediate(0x66556677, output_address, reply_to_ios); // just a random value that works.
}
// Currently unimplemented
INFO_LOG(DVDINTERFACE, "Seek: offset=%09" PRIx64 " (ignoring)", (u64)command_1 << 2);
break;
// Probably only used by Wii

View File

@ -10,7 +10,6 @@
#include "Core/HW/EXI_Device.h"
#include "Core/HW/EXI_DeviceAD16.h"
#include "Core/HW/EXI_DeviceAGP.h"
#include "Core/HW/EXI_DeviceAMBaseboard.h"
#include "Core/HW/EXI_DeviceEthernet.h"
#include "Core/HW/EXI_DeviceGecko.h"
#include "Core/HW/EXI_DeviceIPL.h"
@ -131,10 +130,6 @@ std::unique_ptr<IEXIDevice> EXIDevice_Create(TEXIDevices device_type, const int
result = std::make_unique<CEXIETHERNET>();
break;
case EXIDEVICE_AM_BASEBOARD:
result = std::make_unique<CEXIAMBaseboard>();
break;
case EXIDEVICE_GECKO:
result = std::make_unique<CEXIGecko>();
break;
@ -143,6 +138,7 @@ std::unique_ptr<IEXIDevice> EXIDevice_Create(TEXIDevices device_type, const int
result = std::make_unique<CEXIAgp>(channel_num);
break;
case EXIDEVICE_AM_BASEBOARD:
case EXIDEVICE_NONE:
default:
result = std::make_unique<IEXIDevice>();

View File

@ -17,10 +17,13 @@ enum TEXIDevices : int
EXIDEVICE_AD16,
EXIDEVICE_MIC,
EXIDEVICE_ETH,
// Was used for Triforce in the past, but the implementation is no longer in Dolphin.
// It's kept here so that values below will stay constant.
EXIDEVICE_AM_BASEBOARD,
EXIDEVICE_GECKO,
EXIDEVICE_MEMORYCARDFOLDER, // Only used when creating a device by EXIDevice_Create
// Converted to EXIDEVICE_MEMORYCARD internally
// Only used when creating a device by EXIDevice_Create.
// Converted to EXIDEVICE_MEMORYCARD internally.
EXIDEVICE_MEMORYCARDFOLDER,
EXIDEVICE_AGP,
EXIDEVICE_NONE = (u8)-1
};

View File

@ -1,130 +0,0 @@
// Copyright 2009 Dolphin Emulator Project
// Licensed under GPLv2+
// Refer to the license.txt file included.
#include "Core/HW/EXI.h"
#include "Common/ChunkFile.h"
#include "Common/CommonTypes.h"
#include "Common/Logging/Log.h"
#include "Core/HW/EXI_DeviceAMBaseboard.h"
CEXIAMBaseboard::CEXIAMBaseboard() : m_position(0), m_have_irq(false)
{
}
void CEXIAMBaseboard::SetCS(int cs)
{
ERROR_LOG(SP1, "AM-BB ChipSelect=%d", cs);
if (cs)
m_position = 0;
}
bool CEXIAMBaseboard::IsPresent() const
{
return true;
}
void CEXIAMBaseboard::TransferByte(u8& _byte)
{
/*
ID:
00 00 xx xx xx xx
xx xx 06 04 10 00
CMD:
01 00 00 b3 xx
xx xx xx xx 04
exi_lanctl_write:
ff 02 01 63 xx
xx xx xx xx 04
exi_imr_read:
86 00 00 f5 xx xx xx
xx xx xx xx 04 rr rr
exi_imr_write:
87 80 5c 17 xx
xx xx xx xx 04
exi_isr_read:
82 .. .. .. xx xx xx
xx xx xx xx 04 rr rr
3 byte command, 1 byte checksum
*/
DEBUG_LOG(SP1, "AM-BB > %02x", _byte);
if (m_position < 4)
{
m_command[m_position] = _byte;
_byte = 0xFF;
}
if ((m_position >= 2) && (m_command[0] == 0 && m_command[1] == 0))
{
_byte = "\x06\x04\x10\x00"[(m_position - 2) & 3];
}
else if (m_position == 3)
{
unsigned int checksum = (m_command[0] << 24) | (m_command[1] << 16) | (m_command[2] << 8);
unsigned int bit = 0x80000000UL;
unsigned int check = 0x8D800000UL;
while (bit >= 0x100)
{
if (checksum & bit)
checksum ^= check;
check >>= 1;
bit >>= 1;
}
if (m_command[3] != (checksum & 0xFF))
ERROR_LOG(SP1, "AM-BB cs: %02x, w: %02x", m_command[3], checksum & 0xFF);
}
else
{
if (m_position == 4)
{
_byte = 4;
ERROR_LOG(SP1, "AM-BB COMMAND: %02x %02x %02x", m_command[0], m_command[1], m_command[2]);
if ((m_command[0] == 0xFF) && (m_command[1] == 0) && (m_command[2] == 0))
m_have_irq = true;
else if (m_command[0] == 0x82)
m_have_irq = false;
ExpansionInterface::UpdateInterrupts();
}
else if (m_position > 4)
{
switch (m_command[0])
{
case 0xFF: // lan
_byte = 0xFF;
break;
case 0x86: // imr
_byte = 0x00;
break;
case 0x82: // isr
_byte = m_have_irq ? 0xFF : 0;
break;
default:
_dbg_assert_msg_(SP1, 0, "Unknown AM-BB command");
break;
}
}
else
{
_byte = 0xFF;
}
}
DEBUG_LOG(SP1, "AM-BB < %02x", _byte);
m_position++;
}
bool CEXIAMBaseboard::IsInterruptSet()
{
if (m_have_irq)
ERROR_LOG(SP1, "AM-BB IRQ");
return m_have_irq;
}
void CEXIAMBaseboard::DoState(PointerWrap& p)
{
p.Do(m_position);
p.Do(m_have_irq);
p.Do(m_command);
}

View File

@ -1,26 +0,0 @@
// Copyright 2008 Dolphin Emulator Project
// Licensed under GPLv2+
// Refer to the license.txt file included.
#pragma once
#include "Core/HW/EXI_Device.h"
class PointerWrap;
class CEXIAMBaseboard : public IEXIDevice
{
public:
CEXIAMBaseboard();
void SetCS(int _iCS) override;
bool IsPresent() const override;
bool IsInterruptSet() override;
void DoState(PointerWrap& p) override;
private:
void TransferByte(u8& _uByte) override;
int m_position;
bool m_have_irq;
unsigned char m_command[4];
};

View File

@ -9,7 +9,6 @@
#include "Common/Logging/Log.h"
#include "Common/StringUtil.h"
#include "Core/HW/SI_Device.h"
#include "Core/HW/SI_DeviceAMBaseboard.h"
#include "Core/HW/SI_DeviceDanceMat.h"
#include "Core/HW/SI_DeviceGBA.h"
#include "Core/HW/SI_DeviceGCAdapter.h"
@ -114,8 +113,6 @@ std::unique_ptr<ISIDevice> SIDevice_Create(const SIDevices device, const int por
return std::make_unique<CSIDevice_Keyboard>(device, port_number);
case SIDEVICE_AM_BASEBOARD:
return std::make_unique<CSIDevice_AMBaseboard>(device, port_number);
case SIDEVICE_NONE:
default:
return std::make_unique<CSIDevice_Null>(device, port_number);

View File

@ -62,9 +62,11 @@ enum SIDevices : int
SIDEVICE_GC_STEERING,
SIDEVICE_DANCEMAT,
SIDEVICE_GC_TARUKONGA,
// Was used for Triforce in the past, but the implementation is no longer in Dolphin.
// It's kept here so that values below will stay constant.
SIDEVICE_AM_BASEBOARD,
SIDEVICE_WIIU_ADAPTER,
// not a valid device, used for checking whether enum value is valid
// Not a valid device. Used for checking whether enum values are valid.
SIDEVICE_COUNT,
};

View File

@ -1,451 +0,0 @@
// Copyright 2009 Dolphin Emulator Project
// Licensed under GPLv2+
// Refer to the license.txt file included.
#include <cstdio>
#include <cstring>
#include "Common/CommonTypes.h"
#include "Common/Logging/Log.h"
#include "Common/MsgHandler.h"
#include "Core/HW/GCPad.h"
#include "Core/HW/SI_Device.h"
#include "Core/HW/SI_DeviceAMBaseboard.h"
#include "InputCommon/GCPadStatus.h"
// where to put baseboard debug
#define AMBASEBOARDDEBUG OSREPORT
// "JAMMA Video Standard" I/O
class JVSIOMessage
{
public:
int m_ptr, m_last_start, m_csum;
unsigned char m_msg[0x80];
JVSIOMessage()
{
m_ptr = 0;
m_last_start = 0;
}
void Start(int node)
{
m_last_start = m_ptr;
unsigned char hdr[3] = {0xe0, (unsigned char)node, 0};
m_csum = 0;
AddData(hdr, 3, 1);
}
void AddData(const void* data, size_t len) { AddData((const unsigned char*)data, len); }
void AddData(const char* data) { AddData(data, strlen(data)); }
void AddData(int n)
{
unsigned char cs = n;
AddData(&cs, 1);
}
void End()
{
int len = m_ptr - m_last_start;
m_msg[m_last_start + 2] = len - 2; // assuming len <0xD0
AddData(m_csum + len - 2);
}
void AddData(const unsigned char* dst, size_t len, int sync = 0)
{
while (len--)
{
int c = *dst++;
if (!sync && ((c == 0xE0) || (c == 0xD0)))
{
m_msg[m_ptr++] = 0xD0;
m_msg[m_ptr++] = c - 1;
}
else
{
m_msg[m_ptr++] = c;
}
if (!sync)
m_csum += c;
sync = 0;
if (m_ptr >= 0x80)
PanicAlert("JVSIOMessage overrun!");
}
}
}; // end class JVSIOMessage
// AM-Baseboard device on SI
CSIDevice_AMBaseboard::CSIDevice_AMBaseboard(SIDevices device, int _iDeviceNumber)
: ISIDevice(device, _iDeviceNumber)
{
}
int CSIDevice_AMBaseboard::RunBuffer(u8* _pBuffer, int _iLength)
{
// for debug logging only
ISIDevice::RunBuffer(_pBuffer, _iLength);
int iPosition = 0;
while (iPosition < _iLength)
{
// read the command
EBufferCommands command = static_cast<EBufferCommands>(_pBuffer[iPosition ^ 3]);
iPosition++;
// handle it
switch (command)
{
case CMD_RESET: // returns ID and dip switches
{
*(u32*)&_pBuffer[0] =
SI_AM_BASEBOARD | 0x100; // 0x100 is progressive flag according to dip switch
iPosition = _iLength; // break the while loop
}
break;
case CMD_GCAM:
{
int i;
// calculate checksum over buffer
int csum = 0;
for (i = 0; i < _iLength; ++i)
csum += _pBuffer[i];
unsigned char res[0x80];
int resp = 0;
int real_len = _pBuffer[1 ^ 3];
int p = 2;
static int d10_1 = 0xfe;
memset(res, 0, 0x80);
res[resp++] = 1;
res[resp++] = 1;
#define ptr(x) _pBuffer[(p + x) ^ 3]
while (p < real_len + 2)
{
switch (ptr(0))
{
case 0x10:
{
DEBUG_LOG(AMBASEBOARDDEBUG, "GC-AM: Command 10, %02x (READ STATUS&SWITCHES)", ptr(1));
GCPadStatus pad_status = Pad::GetStatus(m_iDeviceNumber);
res[resp++] = 0x10;
res[resp++] = 0x2;
int d10_0 = 0xdf;
if (pad_status.triggerLeft)
d10_0 &= ~0x80;
if (pad_status.triggerRight)
d10_0 &= ~0x40;
res[resp++] = d10_0;
res[resp++] = d10_1;
break;
}
case 0x12:
ERROR_LOG(AMBASEBOARDDEBUG, "GC-AM: Command 12, %02x %02x", ptr(1), ptr(2));
res[resp++] = 0x12;
res[resp++] = 0x00;
break;
case 0x11:
{
ERROR_LOG(AMBASEBOARDDEBUG, "GC-AM: Command 11, %02x (READ SERIAL NR)", ptr(1));
char string[] = "AADE-01A14964511";
res[resp++] = 0x11;
res[resp++] = 0x10;
memcpy(res + resp, string, 0x10);
resp += 0x10;
break;
}
case 0x15:
ERROR_LOG(AMBASEBOARDDEBUG, "GC-AM: CMD 15, %02x (READ FIRM VERSION)", ptr(1));
res[resp++] = 0x15;
res[resp++] = 0x02;
res[resp++] = 0x00;
res[resp++] = 0x29; // FIRM VERSION
break;
case 0x16:
ERROR_LOG(AMBASEBOARDDEBUG, "GC-AM: Command 16, %02x (READ FPGA VERSION)", ptr(1));
res[resp++] = 0x16;
res[resp++] = 0x02;
res[resp++] = 0x07;
res[resp++] = 0x06; // FPGAVERSION
/*
res[resp++] = 0x16;
res[resp++] = 0x00;
p += 2;
*/
break;
case 0x1f:
{
ERROR_LOG(AMBASEBOARDDEBUG, "GC-AM: Command 1f, %02x %02x %02x %02x %02x (REGION)",
ptr(1), ptr(2), ptr(3), ptr(4), ptr(5));
unsigned char string[] = "\x00\x00\x30\x00"
//"\x01\xfe\x00\x00" // JAPAN
"\x02\xfd\x00\x00" // USA
//"\x03\xfc\x00\x00" // export
"\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff";
res[resp++] = 0x1f;
res[resp++] = 0x14;
for (i = 0; i < 0x14; ++i)
res[resp++] = string[i];
break;
}
case 0x31:
ERROR_LOG(AMBASEBOARDDEBUG, "GC-AM: Command 31 (UNKNOWN)");
res[resp++] = 0x31;
res[resp++] = 0x02;
res[resp++] = 0x00;
res[resp++] = 0x00;
break;
case 0x32:
ERROR_LOG(AMBASEBOARDDEBUG, "GC-AM: Command 32 (UNKNOWN)");
res[resp++] = 0x32;
res[resp++] = 0x02;
res[resp++] = 0x00;
res[resp++] = 0x00;
break;
case 0x40:
case 0x41:
case 0x42:
case 0x43:
case 0x44:
case 0x45:
case 0x46:
case 0x47:
case 0x48:
case 0x49:
case 0x4a:
case 0x4b:
case 0x4c:
case 0x4d:
case 0x4e:
case 0x4f:
{
DEBUG_LOG(AMBASEBOARDDEBUG,
"GC-AM: Command %02x, %02x %02x %02x %02x %02x %02x %02x (JVS IO)", ptr(0),
ptr(1), ptr(2), ptr(3), ptr(4), ptr(5), ptr(6), ptr(7));
int pptr = 2;
JVSIOMessage msg;
msg.Start(0);
msg.AddData(1);
unsigned char jvs_io_buffer[0x80];
int nr_bytes = ptr(pptr + 2); // byte after e0 xx
int jvs_io_length = 0;
for (i = 0; i < nr_bytes + 3; ++i)
jvs_io_buffer[jvs_io_length++] = ptr(pptr + i);
int node = jvs_io_buffer[1];
unsigned char* jvs_io = jvs_io_buffer + 3;
jvs_io_length--; // checksum
while (jvs_io < (jvs_io_buffer + jvs_io_length))
{
int cmd = *jvs_io++;
DEBUG_LOG(AMBASEBOARDDEBUG, "JVS IO, node=%d, command=%02x", node, cmd);
switch (cmd)
{
case 0x10: // get ID
msg.AddData(1);
{
char buffer[12];
sprintf(buffer, "JVS-node %02x", node);
// msg.addData(buffer);
msg.AddData("JAMMA I/O CONTROLLER");
}
msg.AddData(0);
break;
case 0x11: // cmd revision
msg.AddData(1);
msg.AddData(0x11);
break;
case 0x12: // jvs revision
msg.AddData(1);
msg.AddData(0x12);
break;
case 0x13: // com revision
msg.AddData(1);
msg.AddData(0x13);
break;
case 0x14: // get features
msg.AddData(1);
msg.AddData((void*)"\x01\x02\x0a\x00", 4); // 2 player, 10 bit
msg.AddData((void*)"\x02\x02\x00\x00", 4); // 2 coin slots
// msg.addData((void *)"\x03\x02\x08\x00", 4);
msg.AddData((void*)"\x00\x00\x00\x00", 4);
break;
case 0x15:
while (*jvs_io++)
{
};
msg.AddData(1);
break;
case 0x20:
{
int nr_players = *jvs_io++;
int bytes_per_player = *jvs_io++; /* ??? */
int j;
msg.AddData(1);
msg.AddData(0); // tilt
for (i = 0; i < nr_players; ++i)
{
GCPadStatus pad_status = Pad::GetStatus(i);
unsigned char player_data[2] = {0, 0};
if (pad_status.button & PAD_BUTTON_START)
player_data[0] |= 0x80;
if (pad_status.button & PAD_BUTTON_UP)
player_data[0] |= 0x20;
if (pad_status.button & PAD_BUTTON_DOWN)
player_data[0] |= 0x10;
if (pad_status.button & PAD_BUTTON_LEFT)
player_data[0] |= 0x08;
if (pad_status.button & PAD_BUTTON_RIGHT)
player_data[0] |= 0x04;
if (pad_status.button & PAD_BUTTON_A)
player_data[0] |= 0x02;
if (pad_status.button & PAD_BUTTON_B)
player_data[0] |= 0x01;
if (pad_status.button & PAD_BUTTON_X)
player_data[1] |= 0x80;
if (pad_status.button & PAD_BUTTON_Y)
player_data[1] |= 0x40;
if (pad_status.button & PAD_TRIGGER_L)
player_data[1] |= 0x20;
if (pad_status.button & PAD_TRIGGER_R)
player_data[1] |= 0x10;
for (j = 0; j < bytes_per_player; ++j)
msg.AddData(player_data[j & 1]);
}
break;
}
case 0x21: // coin
{
int slots = *jvs_io++;
msg.AddData(1);
GCPadStatus pad_status = Pad::GetStatus(0);
while (slots--)
{
msg.AddData(0);
msg.AddData((pad_status.button & PAD_BUTTON_START) ? 1 : 0);
}
break;
}
case 0x22: // analog
{
break;
}
case 0xf0:
if (*jvs_io++ == 0xD9)
ERROR_LOG(AMBASEBOARDDEBUG, "JVS RESET");
msg.AddData(1);
d10_1 |= 1;
break;
case 0xf1:
node = *jvs_io++;
ERROR_LOG(AMBASEBOARDDEBUG, "JVS SET ADDRESS, node=%d", node);
msg.AddData(node == 1);
break;
default:
break;
}
pptr += jvs_io_length;
}
msg.End();
res[resp++] = ptr(0);
unsigned char* buf = msg.m_msg;
int len = msg.m_ptr;
res[resp++] = len;
for (i = 0; i < len; ++i)
res[resp++] = buf[i];
break;
}
case 0x60:
ERROR_LOG(AMBASEBOARDDEBUG, "GC-AM: Command 60, %02x %02x %02x", ptr(1), ptr(2), ptr(3));
break;
default:
ERROR_LOG(AMBASEBOARDDEBUG, "GC-AM: Command %02x (unknown) %02x %02x %02x %02x %02x",
ptr(0), ptr(1), ptr(2), ptr(3), ptr(4), ptr(5));
break;
}
p += ptr(1) + 2;
}
memset(_pBuffer, 0, _iLength);
int len = resp - 2;
p = 0;
res[1] = len;
csum = 0;
char logptr[1024];
char* log = logptr;
for (i = 0; i < 0x7F; ++i)
{
csum += ptr(i) = res[i];
log += sprintf(log, "%02x ", ptr(i));
}
ptr(0x7f) = ~csum;
DEBUG_LOG(AMBASEBOARDDEBUG, "Command send back: %s", logptr);
#undef ptr
// (tmbinc) hotfix: delay output by one command to work around their broken parser. this took
// me a month to find. ARG!
static unsigned char last[2][0x80];
static int lastptr[2];
{
memcpy(last + 1, _pBuffer, 0x80);
memcpy(_pBuffer, last, 0x80);
memcpy(last, last + 1, 0x80);
lastptr[1] = _iLength;
_iLength = lastptr[0];
lastptr[0] = lastptr[1];
}
iPosition = _iLength;
break;
}
// DEFAULT
default:
{
ERROR_LOG(SERIALINTERFACE, "Unknown SI command (0x%x)", command);
PanicAlert("SI: Unknown command");
iPosition = _iLength;
}
break;
}
}
return iPosition;
}
// Not really used on GC-AM
bool CSIDevice_AMBaseboard::GetData(u32& _Hi, u32& _Low)
{
_Low = 0;
_Hi = 0x00800000;
return true;
}
void CSIDevice_AMBaseboard::SendCommand(u32 _Cmd, u8 _Poll)
{
ERROR_LOG(SERIALINTERFACE, "Unknown direct command (0x%x)", _Cmd);
PanicAlert("SI: (GCAM) Unknown direct command");
}

View File

@ -1,31 +0,0 @@
// Copyright 2008 Dolphin Emulator Project
// Licensed under GPLv2+
// Refer to the license.txt file included.
#pragma once
#include "Core/HW/SI_Device.h"
// triforce (GC-AM) baseboard
class CSIDevice_AMBaseboard : public ISIDevice
{
private:
enum EBufferCommands
{
CMD_RESET = 0x00,
CMD_GCAM = 0x70,
};
public:
// constructor
CSIDevice_AMBaseboard(SIDevices device, int _iDeviceNumber);
// run the SI Buffer
int RunBuffer(u8* _pBuffer, int _iLength) override;
// return true on new data
bool GetData(u32& _Hi, u32& _Low) override;
// send a command directly
void SendCommand(u32 _Cmd, u8 _Poll) override;
};

View File

@ -33,7 +33,6 @@
#define EXIDEV_MIC_STR _trans("Microphone")
#define EXIDEV_BBA_STR _trans("Broadband Adapter")
#define EXIDEV_AGP_STR _trans("Advance Game Port")
#define EXIDEV_AM_BB_STR _trans("AM Baseboard")
#define EXIDEV_GECKO_STR _trans("USB Gecko")
GameCubeConfigPane::GameCubeConfigPane(wxWindow* parent, wxWindowID id) : wxPanel(parent, id)
@ -165,7 +164,6 @@ void GameCubeConfigPane::LoadGUIValues()
sp1_devices.Add(_(DEV_NONE_STR));
sp1_devices.Add(_(DEV_DUMMY_STR));
sp1_devices.Add(_(EXIDEV_BBA_STR));
sp1_devices.Add(_(EXIDEV_AM_BB_STR));
for (int i = 0; i < 3; ++i)
{
@ -200,9 +198,6 @@ void GameCubeConfigPane::LoadGUIValues()
case EXIDEVICE_ETH:
m_exi_devices[i]->SetStringSelection(sp1_devices[2]);
break;
case EXIDEVICE_AM_BASEBOARD:
m_exi_devices[i]->SetStringSelection(sp1_devices[3]);
break;
case EXIDEVICE_DUMMY:
default:
m_exi_devices[i]->SetStringSelection(slot_devices[1]);
@ -282,8 +277,6 @@ void GameCubeConfigPane::ChooseEXIDevice(const wxString& deviceName, int deviceN
tempType = EXIDEVICE_ETH;
else if (!deviceName.compare(_(EXIDEV_AGP_STR)))
tempType = EXIDEVICE_AGP;
else if (!deviceName.compare(_(EXIDEV_AM_BB_STR)))
tempType = EXIDEVICE_AM_BASEBOARD;
else if (!deviceName.compare(_(EXIDEV_GECKO_STR)))
tempType = EXIDEVICE_GECKO;
else if (!deviceName.compare(_(DEV_NONE_STR)))

View File

@ -42,7 +42,7 @@ ControllerConfigDiag::ControllerConfigDiag(wxWindow* const parent)
{
m_gc_pad_type_strs = {{_("None"), _("Standard Controller"), _("GameCube Adapter for Wii U"),
_("Steering Wheel"), _("Dance Mat"), _("DK Bongos"), _("GBA"),
_("Keyboard"), _("AM Baseboard")}};
_("Keyboard")}};
wxBoxSizer* const main_sizer = new wxBoxSizer(wxVERTICAL);
@ -87,13 +87,8 @@ wxStaticBoxSizer* ControllerConfigDiag::CreateGamecubeSizer()
const wxWindowID choice_id = wxWindow::NewControlId();
m_gc_port_choice_ids.emplace(choice_id, i);
// Only add AM-Baseboard to the first pad.
if (i == 0)
pad_type_choices[i] = new wxChoice(this, choice_id, wxDefaultPosition, wxDefaultSize,
m_gc_pad_type_strs.size(), m_gc_pad_type_strs.data());
else
pad_type_choices[i] = new wxChoice(this, choice_id, wxDefaultPosition, wxDefaultSize,
m_gc_pad_type_strs.size() - 1, m_gc_pad_type_strs.data());
pad_type_choices[i] = new wxChoice(this, choice_id, wxDefaultPosition, wxDefaultSize,
m_gc_pad_type_strs.size(), m_gc_pad_type_strs.data());
pad_type_choices[i]->Bind(wxEVT_CHOICE, &ControllerConfigDiag::OnGameCubePortChanged, this);
@ -126,9 +121,6 @@ wxStaticBoxSizer* ControllerConfigDiag::CreateGamecubeSizer()
case SIDEVICE_GC_KEYBOARD:
pad_type_choices[i]->SetStringSelection(m_gc_pad_type_strs[7]);
break;
case SIDEVICE_AM_BASEBOARD:
pad_type_choices[i]->SetStringSelection(m_gc_pad_type_strs[8]);
break;
default:
pad_type_choices[i]->SetStringSelection(m_gc_pad_type_strs[0]);
gamecube_configure_bt[i]->Disable();
@ -483,11 +475,6 @@ void ControllerConfigDiag::OnGameCubePortChanged(wxCommandEvent& event)
tempType = SIDEVICE_GC_KEYBOARD;
gamecube_configure_bt[device_num]->Enable();
}
else if (device_name == m_gc_pad_type_strs[8])
{
tempType = SIDEVICE_AM_BASEBOARD;
gamecube_configure_bt[device_num]->Enable();
}
else
{
tempType = SIDEVICE_NONE;

View File

@ -81,7 +81,7 @@ private:
std::map<wxWindowID, unsigned int> m_gc_port_choice_ids;
std::map<wxWindowID, unsigned int> m_gc_port_config_ids;
std::array<wxString, 9> m_gc_pad_type_strs;
std::array<wxString, 8> m_gc_pad_type_strs;
std::map<wxWindowID, unsigned int> m_wiimote_index_from_ctrl_id;
unsigned int m_orig_wiimote_sources[MAX_BBMOTES];