mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-09-23 17:58:44 +00:00
Added Triforce support
This commit is contained in:
parent
1dbb9a193e
commit
45b137e505
26 changed files with 4995 additions and 46 deletions
|
@ -46,6 +46,7 @@
|
||||||
#define GC_USER_DIR "GC"
|
#define GC_USER_DIR "GC"
|
||||||
#define GBA_USER_DIR "GBA"
|
#define GBA_USER_DIR "GBA"
|
||||||
#define WII_USER_DIR "Wii"
|
#define WII_USER_DIR "Wii"
|
||||||
|
#define TRI_USER_DIR "Triforce"
|
||||||
#define CONFIG_DIR "Config"
|
#define CONFIG_DIR "Config"
|
||||||
#define GAMESETTINGS_DIR "GameSettings"
|
#define GAMESETTINGS_DIR "GameSettings"
|
||||||
#define MAPS_DIR "Maps"
|
#define MAPS_DIR "Maps"
|
||||||
|
@ -154,6 +155,7 @@
|
||||||
// Subdirs in Sys
|
// Subdirs in Sys
|
||||||
#define GC_SYS_DIR "GC"
|
#define GC_SYS_DIR "GC"
|
||||||
#define WII_SYS_DIR "Wii"
|
#define WII_SYS_DIR "Wii"
|
||||||
|
#define TRI_SYS_DIR "Triforce"
|
||||||
|
|
||||||
// Subdirs in Config
|
// Subdirs in Config
|
||||||
#define GRAPHICSMOD_CONFIG_DIR "GraphicMods"
|
#define GRAPHICSMOD_CONFIG_DIR "GraphicMods"
|
||||||
|
|
|
@ -844,6 +844,7 @@ static void RebuildUserDirectories(unsigned int dir_index)
|
||||||
case D_USER_IDX:
|
case D_USER_IDX:
|
||||||
s_user_paths[D_GCUSER_IDX] = s_user_paths[D_USER_IDX] + GC_USER_DIR DIR_SEP;
|
s_user_paths[D_GCUSER_IDX] = s_user_paths[D_USER_IDX] + GC_USER_DIR DIR_SEP;
|
||||||
s_user_paths[D_WIIROOT_IDX] = s_user_paths[D_USER_IDX] + WII_USER_DIR DIR_SEP;
|
s_user_paths[D_WIIROOT_IDX] = s_user_paths[D_USER_IDX] + WII_USER_DIR DIR_SEP;
|
||||||
|
s_user_paths[D_TRIUSER_IDX] = s_user_paths[D_USER_IDX] + TRI_USER_DIR DIR_SEP;
|
||||||
s_user_paths[D_CONFIG_IDX] = s_user_paths[D_USER_IDX] + CONFIG_DIR DIR_SEP;
|
s_user_paths[D_CONFIG_IDX] = s_user_paths[D_USER_IDX] + CONFIG_DIR DIR_SEP;
|
||||||
s_user_paths[D_GAMESETTINGS_IDX] = s_user_paths[D_USER_IDX] + GAMESETTINGS_DIR DIR_SEP;
|
s_user_paths[D_GAMESETTINGS_IDX] = s_user_paths[D_USER_IDX] + GAMESETTINGS_DIR DIR_SEP;
|
||||||
s_user_paths[D_MAPS_IDX] = s_user_paths[D_USER_IDX] + MAPS_DIR DIR_SEP;
|
s_user_paths[D_MAPS_IDX] = s_user_paths[D_USER_IDX] + MAPS_DIR DIR_SEP;
|
||||||
|
|
|
@ -29,6 +29,7 @@ enum
|
||||||
D_USER_IDX,
|
D_USER_IDX,
|
||||||
D_GCUSER_IDX,
|
D_GCUSER_IDX,
|
||||||
D_WIIROOT_IDX, // always points to User/Wii or global user-configured directory
|
D_WIIROOT_IDX, // always points to User/Wii or global user-configured directory
|
||||||
|
D_TRIUSER_IDX,
|
||||||
D_SESSION_WIIROOT_IDX, // may point to minimal temporary directory for determinism
|
D_SESSION_WIIROOT_IDX, // may point to minimal temporary directory for determinism
|
||||||
D_CONFIG_IDX, // global settings
|
D_CONFIG_IDX, // global settings
|
||||||
D_GAMESETTINGS_IDX, // user-specified settings which override both the global and the default
|
D_GAMESETTINGS_IDX, // user-specified settings which override both the global and the default
|
||||||
|
|
|
@ -28,6 +28,7 @@ enum class LogType : int
|
||||||
DSP_MAIL,
|
DSP_MAIL,
|
||||||
DSPINTERFACE,
|
DSPINTERFACE,
|
||||||
DVDINTERFACE,
|
DVDINTERFACE,
|
||||||
|
DVDINTERFACE_AMMB,
|
||||||
DYNA_REC,
|
DYNA_REC,
|
||||||
EXPANSIONINTERFACE,
|
EXPANSIONINTERFACE,
|
||||||
FILEMON,
|
FILEMON,
|
||||||
|
@ -59,6 +60,9 @@ enum class LogType : int
|
||||||
PROCESSORINTERFACE,
|
PROCESSORINTERFACE,
|
||||||
POWERPC,
|
POWERPC,
|
||||||
SERIALINTERFACE,
|
SERIALINTERFACE,
|
||||||
|
SERIALINTERFACE_AMBB,
|
||||||
|
SERIALINTERFACE_CARD,
|
||||||
|
SERIALINTERFACE_JVSIO,
|
||||||
SP1,
|
SP1,
|
||||||
SYMBOLS,
|
SYMBOLS,
|
||||||
VIDEO,
|
VIDEO,
|
||||||
|
|
|
@ -113,6 +113,7 @@ LogManager::LogManager()
|
||||||
m_log[LogType::DSP_MAIL] = {"DSPMails", "DSP Mails"};
|
m_log[LogType::DSP_MAIL] = {"DSPMails", "DSP Mails"};
|
||||||
m_log[LogType::DSPINTERFACE] = {"DSP", "DSP Interface"};
|
m_log[LogType::DSPINTERFACE] = {"DSP", "DSP Interface"};
|
||||||
m_log[LogType::DVDINTERFACE] = {"DVD", "DVD Interface"};
|
m_log[LogType::DVDINTERFACE] = {"DVD", "DVD Interface"};
|
||||||
|
m_log[LogType::DVDINTERFACE_AMMB] = { "DVD", "AMMB Interface" };
|
||||||
m_log[LogType::DYNA_REC] = {"JIT", "JIT Dynamic Recompiler"};
|
m_log[LogType::DYNA_REC] = {"JIT", "JIT Dynamic Recompiler"};
|
||||||
m_log[LogType::EXPANSIONINTERFACE] = {"EXI", "Expansion Interface"};
|
m_log[LogType::EXPANSIONINTERFACE] = {"EXI", "Expansion Interface"};
|
||||||
m_log[LogType::FILEMON] = {"FileMon", "File Monitor"};
|
m_log[LogType::FILEMON] = {"FileMon", "File Monitor"};
|
||||||
|
@ -144,6 +145,9 @@ LogManager::LogManager()
|
||||||
m_log[LogType::PROCESSORINTERFACE] = {"PI", "Processor Interface"};
|
m_log[LogType::PROCESSORINTERFACE] = {"PI", "Processor Interface"};
|
||||||
m_log[LogType::POWERPC] = {"PowerPC", "PowerPC IBM CPU"};
|
m_log[LogType::POWERPC] = {"PowerPC", "PowerPC IBM CPU"};
|
||||||
m_log[LogType::SERIALINTERFACE] = {"SI", "Serial Interface"};
|
m_log[LogType::SERIALINTERFACE] = {"SI", "Serial Interface"};
|
||||||
|
m_log[LogType::SERIALINTERFACE_AMBB] = { "SI", "AMBB Interface" };
|
||||||
|
m_log[LogType::SERIALINTERFACE_CARD] = { "SI", "CARD Interface" };
|
||||||
|
m_log[LogType::SERIALINTERFACE_JVSIO] = { "SI", "JVS-I/O" };
|
||||||
m_log[LogType::SP1] = {"SP1", "Serial Port 1"};
|
m_log[LogType::SP1] = {"SP1", "Serial Port 1"};
|
||||||
m_log[LogType::SYMBOLS] = {"SYMBOLS", "Symbols"};
|
m_log[LogType::SYMBOLS] = {"SYMBOLS", "Symbols"};
|
||||||
m_log[LogType::VIDEO] = {"Video", "Video Backend"};
|
m_log[LogType::VIDEO] = {"Video", "Video Backend"};
|
||||||
|
|
|
@ -22,6 +22,7 @@
|
||||||
#include "Core/Debugger/BranchWatch.h"
|
#include "Core/Debugger/BranchWatch.h"
|
||||||
#include "Core/HLE/HLE.h"
|
#include "Core/HLE/HLE.h"
|
||||||
#include "Core/HW/DVD/DVDInterface.h"
|
#include "Core/HW/DVD/DVDInterface.h"
|
||||||
|
#include "Core/HW/DVD/AMMediaboard.h"
|
||||||
#include "Core/HW/EXI/EXI_DeviceIPL.h"
|
#include "Core/HW/EXI/EXI_DeviceIPL.h"
|
||||||
#include "Core/HW/Memmap.h"
|
#include "Core/HW/Memmap.h"
|
||||||
#include "Core/IOS/DI/DI.h"
|
#include "Core/IOS/DI/DI.h"
|
||||||
|
@ -227,12 +228,23 @@ bool CBoot::RunApploader(Core::System& system, const Core::CPUThreadGuard& guard
|
||||||
ppc_state.pc = ppc_state.gpr[3];
|
ppc_state.pc = ppc_state.gpr[3];
|
||||||
|
|
||||||
branch_watch.SetRecordingActive(guard, resume_branch_watch);
|
branch_watch.SetRecordingActive(guard, resume_branch_watch);
|
||||||
// Blank out session key (https://debugmo.de/2008/05/part-2-dumping-the-media-board/)
|
|
||||||
if (volume.GetVolumeType() == DiscIO::Platform::Triforce)
|
// Check for Triforce board being connected
|
||||||
|
const ExpansionInterface::EXIDeviceType Type = Config::Get(Config::MAIN_SERIAL_PORT_1);
|
||||||
|
bool enable_gcam = (Type == ExpansionInterface::EXIDeviceType::Baseboard) ? 1 : 0;
|
||||||
|
if (enable_gcam)
|
||||||
{
|
{
|
||||||
auto& memory = system.GetMemory();
|
auto& memory = system.GetMemory();
|
||||||
|
u32 dsize = volume.GetDataSize();
|
||||||
|
|
||||||
memory.Memset(0, 0, 12);
|
// Load game into RAM, like on the actual Triforce
|
||||||
|
u8* dimm_disc = AMMediaboard::InitDIMM(dsize);
|
||||||
|
|
||||||
|
volume.Read(0, dsize, dimm_disc, DiscIO::PARTITION_NONE);
|
||||||
|
|
||||||
|
// Triforce disc register obfucation
|
||||||
|
AMMediaboard::InitKeys(memory.Read_U32(0), memory.Read_U32(4), memory.Read_U32(8));
|
||||||
|
AMMediaboard::FirmwareMap(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -183,6 +183,8 @@ add_library(core
|
||||||
HW/DSPLLE/DSPSymbols.h
|
HW/DSPLLE/DSPSymbols.h
|
||||||
HW/DVD/DVDInterface.cpp
|
HW/DVD/DVDInterface.cpp
|
||||||
HW/DVD/DVDInterface.h
|
HW/DVD/DVDInterface.h
|
||||||
|
HW/DVD/AMMediaboard.cpp
|
||||||
|
HW/DVD/AMMediaboard.h
|
||||||
HW/DVD/DVDMath.cpp
|
HW/DVD/DVDMath.cpp
|
||||||
HW/DVD/DVDMath.h
|
HW/DVD/DVDMath.h
|
||||||
HW/DVD/DVDThread.cpp
|
HW/DVD/DVDThread.cpp
|
||||||
|
@ -276,6 +278,8 @@ add_library(core
|
||||||
HW/SI/SI_DeviceGCSteeringWheel.h
|
HW/SI/SI_DeviceGCSteeringWheel.h
|
||||||
HW/SI/SI_DeviceKeyboard.cpp
|
HW/SI/SI_DeviceKeyboard.cpp
|
||||||
HW/SI/SI_DeviceKeyboard.h
|
HW/SI/SI_DeviceKeyboard.h
|
||||||
|
HW/SI/SI_DeviceAMBaseboard.cpp
|
||||||
|
HW/SI/SI_DeviceAMBaseboard.h
|
||||||
HW/SI/SI_DeviceNull.cpp
|
HW/SI/SI_DeviceNull.cpp
|
||||||
HW/SI/SI_DeviceNull.h
|
HW/SI/SI_DeviceNull.h
|
||||||
HW/SI/SI.cpp
|
HW/SI/SI.cpp
|
||||||
|
|
|
@ -52,6 +52,7 @@
|
||||||
#include "Core/HLE/HLE.h"
|
#include "Core/HLE/HLE.h"
|
||||||
#include "Core/HW/CPU.h"
|
#include "Core/HW/CPU.h"
|
||||||
#include "Core/HW/DSP.h"
|
#include "Core/HW/DSP.h"
|
||||||
|
#include "Core/HW/DVD/AMMediaboard.h"
|
||||||
#include "Core/HW/EXI/EXI.h"
|
#include "Core/HW/EXI/EXI.h"
|
||||||
#include "Core/HW/GBAPad.h"
|
#include "Core/HW/GBAPad.h"
|
||||||
#include "Core/HW/GCKeyboard.h"
|
#include "Core/HW/GCKeyboard.h"
|
||||||
|
@ -301,6 +302,13 @@ void Stop(Core::System& system) // - Hammertime!
|
||||||
|
|
||||||
system.GetFifo().ExitGpuLoop();
|
system.GetFifo().ExitGpuLoop();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const ExpansionInterface::EXIDeviceType Type = Config::Get(Config::MAIN_SERIAL_PORT_1);
|
||||||
|
|
||||||
|
if ((Type == ExpansionInterface::EXIDeviceType::Baseboard))
|
||||||
|
{
|
||||||
|
AMMediaboard::Shutdown();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void DeclareAsCPUThread()
|
void DeclareAsCPUThread()
|
||||||
|
|
1863
Source/Core/Core/HW/DVD/AMMediaboard.cpp
Normal file
1863
Source/Core/Core/HW/DVD/AMMediaboard.cpp
Normal file
File diff suppressed because it is too large
Load diff
216
Source/Core/Core/HW/DVD/AMMediaboard.h
Normal file
216
Source/Core/Core/HW/DVD/AMMediaboard.h
Normal file
|
@ -0,0 +1,216 @@
|
||||||
|
// Copyright 2017 Dolphin Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include <optional>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "Common/CommonTypes.h"
|
||||||
|
|
||||||
|
class PointerWrap;
|
||||||
|
|
||||||
|
namespace Core
|
||||||
|
{
|
||||||
|
class System;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace File
|
||||||
|
{
|
||||||
|
class IOFile;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum GameType
|
||||||
|
{
|
||||||
|
FZeroAX = 1,
|
||||||
|
FZeroAXMonster,
|
||||||
|
MarioKartGP,
|
||||||
|
MarioKartGP2,
|
||||||
|
VirtuaStriker3,
|
||||||
|
VirtuaStriker4,
|
||||||
|
GekitouProYakyuu,
|
||||||
|
KeyOfAvalon,
|
||||||
|
FirmwareUpdate
|
||||||
|
};
|
||||||
|
enum MediaType
|
||||||
|
{
|
||||||
|
GDROM = 1,
|
||||||
|
NAND,
|
||||||
|
};
|
||||||
|
enum MediaBoardType
|
||||||
|
{
|
||||||
|
NANDMaskBoardHDD = 0,
|
||||||
|
NANDMaskBoardMask = 1,
|
||||||
|
NANDMaskBoardNAND = 2,
|
||||||
|
DIMMBoardType3 = 4,
|
||||||
|
};
|
||||||
|
enum MediaBoardStatus
|
||||||
|
{
|
||||||
|
Initializing = 0,
|
||||||
|
CheckingNetwork = 1,
|
||||||
|
SystemDisc = 2,
|
||||||
|
TestingGameProgram = 3,
|
||||||
|
LoadingGameProgram = 4,
|
||||||
|
LoadedGameProgram = 5,
|
||||||
|
Error = 6
|
||||||
|
};
|
||||||
|
enum InquiryType
|
||||||
|
{
|
||||||
|
Version1 = 0x21484100,
|
||||||
|
Version2 = 0x29484100
|
||||||
|
};
|
||||||
|
|
||||||
|
#define SocketCheck(x) (x <= 0x3F ? x : 0)
|
||||||
|
|
||||||
|
namespace AMMediaboard
|
||||||
|
{
|
||||||
|
enum class AMMBCommand : u16
|
||||||
|
{
|
||||||
|
Unknown_000 = 0x000,
|
||||||
|
GetDIMMSize = 0x001,
|
||||||
|
|
||||||
|
Inquiry = 0x12,
|
||||||
|
Read = 0xa8,
|
||||||
|
Write = 0xaa,
|
||||||
|
Execute = 0xab,
|
||||||
|
|
||||||
|
GetMediaBoardStatus = 0x100,
|
||||||
|
GetSegaBootVersion = 0x101,
|
||||||
|
GetSystemFlags = 0x102,
|
||||||
|
GetMediaBoardSerial = 0x103,
|
||||||
|
Unknown_104 = 0x104,
|
||||||
|
|
||||||
|
NetworkReInit = 0x204,
|
||||||
|
|
||||||
|
TestHardware = 0x301,
|
||||||
|
|
||||||
|
// Network used by Mario Kart GPs
|
||||||
|
Accept = 0x401,
|
||||||
|
Bind = 0x402,
|
||||||
|
Closesocket = 0x403,
|
||||||
|
Connect = 0x404,
|
||||||
|
GetIPbyDNS = 0x405,
|
||||||
|
InetAddr = 0x406,
|
||||||
|
Ioctl = 0x407, // Unused
|
||||||
|
Listen = 0x408,
|
||||||
|
Recv = 0x409,
|
||||||
|
Send = 0x40A,
|
||||||
|
Socket = 0x40B,
|
||||||
|
Select = 0x40C,
|
||||||
|
Shutdown = 0x40D, // Unused
|
||||||
|
SetSockOpt = 0x40E,
|
||||||
|
GetSockOpt = 0x40F, // Unused
|
||||||
|
SetTimeOuts = 0x410,
|
||||||
|
GetLastError = 0x411,
|
||||||
|
RouteAdd = 0x412, // Unused
|
||||||
|
RouteDelete = 0x413, // Unused
|
||||||
|
GetParambyDHCPExec = 0x414,
|
||||||
|
ModifyMyIPaddr = 0x415,
|
||||||
|
Recvfrom = 0x416, // Unused
|
||||||
|
Sendto = 0x417, // Unused
|
||||||
|
RecvDimmImage = 0x418, // Unused
|
||||||
|
SendDimmImage = 0x419, // Unused
|
||||||
|
|
||||||
|
// Network used by F-Zero AX
|
||||||
|
InitLink = 0x601,
|
||||||
|
Unknown_605 = 0x605,
|
||||||
|
SetupLink = 0x606,
|
||||||
|
SearchDevices = 0x607,
|
||||||
|
Unknown_608 = 0x608,
|
||||||
|
Unknown_614 = 0x614,
|
||||||
|
|
||||||
|
// NETDIMM Commands
|
||||||
|
Unknown_001 = 0x001,
|
||||||
|
GetNetworkFirmVersion = 0x101,
|
||||||
|
Unknown_103 = 0x103,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum MediaBoardAddress : u32
|
||||||
|
{
|
||||||
|
MediaBoardStatus1 = 0x80000000,
|
||||||
|
MediaBoardStatus2 = 0x80000020,
|
||||||
|
MediaBoardStatus3 = 0x80000040,
|
||||||
|
|
||||||
|
FirmwareStatus1 = 0x80000120,
|
||||||
|
FirmwareStatus2 = 0x80000140,
|
||||||
|
|
||||||
|
BackupMemory = 0x000006A0,
|
||||||
|
|
||||||
|
DIMMMemory = 0x1F000000,
|
||||||
|
DIMMMemory2 = 0xFF000000,
|
||||||
|
|
||||||
|
DIMMExtraSettings = 0x1FFEFFE0,
|
||||||
|
|
||||||
|
NetworkControl = 0xFFFF0000,
|
||||||
|
|
||||||
|
DIMMCommandVersion1 = 0x1F900000,
|
||||||
|
DIMMCommandVersion2 = 0x84000000,
|
||||||
|
DIMMCommandVersion2_2 = 0x89000000,
|
||||||
|
DIMMCommandExecute2 = 0x88000000,
|
||||||
|
|
||||||
|
NetworkCommandAddress = 0x1F800200,
|
||||||
|
NetworkCommandAddress2 = 0x89040200,
|
||||||
|
|
||||||
|
NetworkBufferAddress1 = 0x1FA00000,
|
||||||
|
NetworkBufferAddress2 = 0x1FD00000,
|
||||||
|
NetworkBufferAddress3 = 0x89100000,
|
||||||
|
NetworkBufferAddress4 = 0x89180000,
|
||||||
|
NetworkBufferAddress5 = 0x1FB00000,
|
||||||
|
|
||||||
|
FirmwareAddress = 0x84800000,
|
||||||
|
|
||||||
|
FirmwareMagicWrite1 = 0x00600000,
|
||||||
|
FirmwareMagicWrite2 = 0x00700000,
|
||||||
|
};
|
||||||
|
|
||||||
|
// Mario Kart GP2 has a complete list of them
|
||||||
|
// but in japanese
|
||||||
|
// They somewhat match WSA errors codes
|
||||||
|
enum SocketStatusCodes
|
||||||
|
{
|
||||||
|
SSC_E_4 = -4, // Failure (abnormal argument)
|
||||||
|
SSC_E_3 = -3, // Success (unsupported command)
|
||||||
|
SSC_E_2 =
|
||||||
|
-2, // Failure (failed to send, abnormal argument, or communication condition violation)
|
||||||
|
SSC_E_1 = -1, // Failure (error termination)
|
||||||
|
|
||||||
|
SSC_EINTR = 4, // An interrupt occurred before data reception was completed
|
||||||
|
SSC_EBADF = 9, // Invalid descriptor
|
||||||
|
SSC_E_11 = 11, // Send operation was blocked on a non-blocking mode socket
|
||||||
|
SSC_EACCES = 13, // The socket does not support broadcast addresses, but the destination address
|
||||||
|
// is a broadcast address
|
||||||
|
SSC_EFAULT =
|
||||||
|
14, // The name argument specifies a location other than an address used by the process.
|
||||||
|
SSC_E_23 = 23, // System file table is full.
|
||||||
|
SSC_AEMFILE = 24, // Process descriptor table is full.
|
||||||
|
SSC_EMSGSIZE =
|
||||||
|
36, // Socket tried to send message without splitting, but message size is too large.
|
||||||
|
SSC_EAFNOSUPPORT = 47, // Address prohibited for use on this socket.
|
||||||
|
SSC_EADDRINUSE = 48, // Address already in use.
|
||||||
|
SSC_EADDRNOTAVAIL = 49, // Prohibited address.
|
||||||
|
SSC_E_50 = 50, // Non-socket descriptor.
|
||||||
|
SSC_ENETUNREACH = 51, // Cannot access specified network.
|
||||||
|
SSC_ENOBUFS = 55, // Insufficient buffer
|
||||||
|
SSC_EISCONN = 56, // Already connected socket
|
||||||
|
SSC_ENOTCONN = 57, // No connection for connection-type socket
|
||||||
|
SSC_ETIMEDOUT = 60, // Timeout
|
||||||
|
SSC_ECONNREFUSED = 61, // Connection request forcibly rejected
|
||||||
|
SSC_EHOSTUNREACH = 65, // Remote host cannot be reached
|
||||||
|
SSC_EHOSTDOWN = 67, // Remote host is down
|
||||||
|
SSC_EWOULDBLOCK = 70, // Socket is in non-blocking mode and connection has not been completed
|
||||||
|
SSC_E_69 = 69, // Socket is in non-blocking mode and a previously issued Connect command has not
|
||||||
|
// been completed
|
||||||
|
SSC_SUCCESS = 70,
|
||||||
|
};
|
||||||
|
|
||||||
|
void Init(void);
|
||||||
|
void FirmwareMap(bool on);
|
||||||
|
u8* InitDIMM(u32 size);
|
||||||
|
void InitKeys(u32 KeyA, u32 KeyB, u32 KeyC);
|
||||||
|
u32 ExecuteCommand(std::array<u32, 3>& DICMDBUF, u32 Address, u32 Length);
|
||||||
|
u32 GetGameType(void);
|
||||||
|
u32 GetMediaType(void);
|
||||||
|
void Shutdown(void);
|
||||||
|
}; // namespace AMMediaboard
|
|
@ -28,6 +28,7 @@
|
||||||
#include "Core/DolphinAnalytics.h"
|
#include "Core/DolphinAnalytics.h"
|
||||||
#include "Core/HW/AudioInterface.h"
|
#include "Core/HW/AudioInterface.h"
|
||||||
#include "Core/HW/DVD/DVDMath.h"
|
#include "Core/HW/DVD/DVDMath.h"
|
||||||
|
#include "Core/HW/DVD/AMMediaboard.h"
|
||||||
#include "Core/HW/DVD/DVDThread.h"
|
#include "Core/HW/DVD/DVDThread.h"
|
||||||
#include "Core/HW/EXI/EXI_DeviceIPL.h"
|
#include "Core/HW/EXI/EXI_DeviceIPL.h"
|
||||||
#include "Core/HW/MMIO.h"
|
#include "Core/HW/MMIO.h"
|
||||||
|
@ -269,6 +270,8 @@ void DVDInterface::Init()
|
||||||
m_DIIMMBUF = 0;
|
m_DIIMMBUF = 0;
|
||||||
m_DICFG.Hex = 0;
|
m_DICFG.Hex = 0;
|
||||||
m_DICFG.CONFIG = 1; // Disable bootrom descrambler
|
m_DICFG.CONFIG = 1; // Disable bootrom descrambler
|
||||||
|
m_DICFG.Hex |= 8; /* The Triforce IPL checks this bit
|
||||||
|
to set the physical memory to either 50MB(unset) or 24MB(set) */
|
||||||
|
|
||||||
ResetDrive(false);
|
ResetDrive(false);
|
||||||
|
|
||||||
|
@ -282,6 +285,13 @@ void DVDInterface::Init()
|
||||||
|
|
||||||
u64 userdata = PackFinishExecutingCommandUserdata(ReplyType::DTK, DIInterruptType::TCINT);
|
u64 userdata = PackFinishExecutingCommandUserdata(ReplyType::DTK, DIInterruptType::TCINT);
|
||||||
core_timing.ScheduleEvent(0, m_finish_executing_command, userdata);
|
core_timing.ScheduleEvent(0, m_finish_executing_command, userdata);
|
||||||
|
|
||||||
|
const ExpansionInterface::EXIDeviceType Type = Config::Get(Config::MAIN_SERIAL_PORT_1);
|
||||||
|
m_enable_gcam = (Type == ExpansionInterface::EXIDeviceType::Baseboard) ? 1 : 0;
|
||||||
|
if (m_enable_gcam)
|
||||||
|
{
|
||||||
|
AMMediaboard::Init();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Resets state on the MN102 chip in the drive itself, but not the DI registers exposed on the
|
// Resets state on the MN102 chip in the drive itself, but not the DI registers exposed on the
|
||||||
|
@ -753,6 +763,26 @@ void DVDInterface::ExecuteCommand(ReplyType reply_type)
|
||||||
DIInterruptType interrupt_type = DIInterruptType::TCINT;
|
DIInterruptType interrupt_type = DIInterruptType::TCINT;
|
||||||
bool command_handled_by_thread = false;
|
bool command_handled_by_thread = false;
|
||||||
|
|
||||||
|
if (m_enable_gcam)
|
||||||
|
{
|
||||||
|
u32 ret = AMMediaboard::ExecuteCommand(m_DICMDBUF, m_DIMAR, m_DILENGTH);
|
||||||
|
if (ret != 1)
|
||||||
|
{
|
||||||
|
if (m_DICMDBUF[0] == 0x12000000)
|
||||||
|
m_DIIMMBUF = ret;
|
||||||
|
|
||||||
|
// Transfer is done
|
||||||
|
m_DICR.TSTART = 0;
|
||||||
|
m_DIMAR += m_DILENGTH;
|
||||||
|
m_DILENGTH = 0;
|
||||||
|
GenerateDIInterrupt(DIInterruptType::TCINT);
|
||||||
|
m_error_code = DriveError::None;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
m_DICMDBUF[1] >>= 2;
|
||||||
|
// Normal read command pass on to normal handling
|
||||||
|
}
|
||||||
|
|
||||||
// Swaps endian of Triforce DI commands, and zeroes out random bytes to prevent unknown read
|
// Swaps endian of Triforce DI commands, and zeroes out random bytes to prevent unknown read
|
||||||
// subcommand errors
|
// subcommand errors
|
||||||
auto& dvd_thread = m_system.GetDVDThread();
|
auto& dvd_thread = m_system.GetDVDThread();
|
||||||
|
|
|
@ -279,6 +279,9 @@ private:
|
||||||
bool m_enable_dtk = false;
|
bool m_enable_dtk = false;
|
||||||
u8 m_dtk_buffer_length = 0; // TODO: figure out how this affects the regular buffer
|
u8 m_dtk_buffer_length = 0; // TODO: figure out how this affects the regular buffer
|
||||||
|
|
||||||
|
// Triforce
|
||||||
|
bool m_enable_gcam = false;
|
||||||
|
|
||||||
// Disc drive state
|
// Disc drive state
|
||||||
DriveState m_drive_state = DriveState::Ready;
|
DriveState m_drive_state = DriveState::Ready;
|
||||||
DriveError m_error_code = DriveError::None;
|
DriveError m_error_code = DriveError::None;
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
#include "Core/HW/EXI/EXI_DeviceIPL.h"
|
#include "Core/HW/EXI/EXI_DeviceIPL.h"
|
||||||
#include "Core/HW/EXI/EXI_DeviceMemoryCard.h"
|
#include "Core/HW/EXI/EXI_DeviceMemoryCard.h"
|
||||||
#include "Core/HW/EXI/EXI_DeviceModem.h"
|
#include "Core/HW/EXI/EXI_DeviceModem.h"
|
||||||
|
#include "Core/HW/EXI/EXI_DeviceBaseboard.h"
|
||||||
#include "Core/HW/Memmap.h"
|
#include "Core/HW/Memmap.h"
|
||||||
#include "Core/System.h"
|
#include "Core/System.h"
|
||||||
|
|
||||||
|
|
|
@ -1,21 +1,139 @@
|
||||||
// Copyright 2013 Dolphin Emulator Project
|
// Copyright 2017 Dolphin Emulator Project
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
#include "Core/HW/EXI/EXI_DeviceBaseboard.h"
|
#include "Core/HW/EXI/EXI_DeviceBaseboard.h"
|
||||||
|
#include <algorithm>
|
||||||
|
#include <memory>
|
||||||
|
#include <optional>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include <fmt/format.h>
|
||||||
|
|
||||||
#include "Common/Assert.h"
|
|
||||||
#include "Common/ChunkFile.h"
|
|
||||||
#include "Common/CommonTypes.h"
|
#include "Common/CommonTypes.h"
|
||||||
|
#include "Common/Config/Config.h"
|
||||||
|
#include "Common/FileUtil.h"
|
||||||
|
#include "Common/IOFile.h"
|
||||||
|
#include "Common/IniFile.h"
|
||||||
#include "Common/Logging/Log.h"
|
#include "Common/Logging/Log.h"
|
||||||
|
#include "Core/Boot/Boot.h"
|
||||||
|
#include "Core/BootManager.h"
|
||||||
|
#include "Core/Config/MainSettings.h"
|
||||||
|
#include "Core/Config/SYSCONFSettings.h"
|
||||||
|
#include "Core/ConfigLoaders/BaseConfigLoader.h"
|
||||||
|
#include "Core/ConfigLoaders/NetPlayConfigLoader.h"
|
||||||
|
#include "Core/ConfigManager.h"
|
||||||
|
#include "Core/Core.h"
|
||||||
|
#include "Core/HW/DVD/AMMediaboard.h"
|
||||||
|
#include "Core/HW/DVD/DVDInterface.h"
|
||||||
|
#include "Core/HW/EXI/EXI.h"
|
||||||
|
#include "Core/HW/EXI/EXI_Device.h"
|
||||||
|
#include "Core/HW/MMIO.h"
|
||||||
|
#include "Core/HW/Memmap.h"
|
||||||
|
#include "Core/HW/SI/SI.h"
|
||||||
|
#include "Core/HW/SI/SI_Device.h"
|
||||||
|
#include "Core/HW/Sram.h"
|
||||||
|
#include "Core/HW/WiimoteReal/WiimoteReal.h"
|
||||||
|
#include "Core/Movie.h"
|
||||||
|
#include "Core/NetPlayProto.h"
|
||||||
|
#include "Core/PowerPC/PowerPC.h"
|
||||||
|
#include "Core/System.h"
|
||||||
|
#include "Core/WiiRoot.h"
|
||||||
|
#include "DiscIO/Enums.h"
|
||||||
|
|
||||||
|
bool g_interrupt_set = false;
|
||||||
|
u32 g_irq_timer = 0;
|
||||||
|
u32 g_irq_status = 0;
|
||||||
|
|
||||||
|
static u16 CheckSum(u8* Data, u32 Length)
|
||||||
|
{
|
||||||
|
u16 check = 0;
|
||||||
|
|
||||||
|
for (u32 i = 0; i < Length; i++)
|
||||||
|
{
|
||||||
|
check += Data[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
return check;
|
||||||
|
}
|
||||||
|
|
||||||
namespace ExpansionInterface
|
namespace ExpansionInterface
|
||||||
{
|
{
|
||||||
CEXIBaseboard::CEXIBaseboard(Core::System& system) : IEXIDevice(system)
|
|
||||||
|
void GenerateInterrupt(int flag)
|
||||||
{
|
{
|
||||||
|
auto& system = Core::System::GetInstance();
|
||||||
|
|
||||||
|
g_interrupt_set = true;
|
||||||
|
g_irq_timer = 0;
|
||||||
|
g_irq_status = flag;
|
||||||
|
|
||||||
|
system.GetExpansionInterface().UpdateInterrupts();
|
||||||
|
}
|
||||||
|
|
||||||
|
CEXIBaseboard::CEXIBaseboard(Core::System& system) : IEXIDevice(system), m_position(0)
|
||||||
|
{
|
||||||
|
std::string backup_Filename(File::GetUserPath(D_TRIUSER_IDX) + "tribackup_" +
|
||||||
|
SConfig::GetInstance().GetTriforceID().c_str() + ".bin");
|
||||||
|
|
||||||
|
if (File::Exists(backup_Filename))
|
||||||
|
{
|
||||||
|
m_backup = new File::IOFile(backup_Filename, "rb+");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_backup = new File::IOFile(backup_Filename, "wb+");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Some games share the same ID Client/Server
|
||||||
|
if (!m_backup->IsGood())
|
||||||
|
{
|
||||||
|
PanicAlertFmt("Failed to open {}\nFile might be in use.", backup_Filename.c_str() );
|
||||||
|
|
||||||
|
std::srand(static_cast<u32>(std::time(nullptr)));
|
||||||
|
|
||||||
|
backup_Filename = File::GetUserPath(D_TRIUSER_IDX) + "tribackup_tmp_" + std::to_string(rand()) +
|
||||||
|
SConfig::GetInstance().GetTriforceID().c_str() + ".bin";
|
||||||
|
|
||||||
|
m_backup = new File::IOFile(backup_Filename, "wb+");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Virtua Striker 4 and Gekitou Pro Yakyuu need a higher FIRM version
|
||||||
|
// Which is read from the backup data?!
|
||||||
|
if (AMMediaboard::GetGameType() == VirtuaStriker4 ||
|
||||||
|
AMMediaboard::GetGameType() == GekitouProYakyuu)
|
||||||
|
{
|
||||||
|
if (m_backup->GetSize() != 0)
|
||||||
|
{
|
||||||
|
u8* data = new u8[m_backup->GetSize()];
|
||||||
|
|
||||||
|
m_backup->ReadBytes(data, m_backup->GetSize());
|
||||||
|
|
||||||
|
// Set FIRM version
|
||||||
|
*(u16*)(data + 0x12) = 0x1703;
|
||||||
|
*(u16*)(data + 0x212) = 0x1703;
|
||||||
|
|
||||||
|
// Update checksum
|
||||||
|
*(u16*)(data + 0x0A) = Common::swap16(CheckSum(data + 0xC, 0x1F4));
|
||||||
|
*(u16*)(data + 0x20A) = Common::swap16(CheckSum(data + 0x20C, 0x1F4));
|
||||||
|
|
||||||
|
m_backup->Seek(0, File::SeekOrigin::Begin);
|
||||||
|
m_backup->WriteBytes(data, m_backup->GetSize());
|
||||||
|
m_backup->Flush();
|
||||||
|
|
||||||
|
delete[] data;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
CEXIBaseboard::~CEXIBaseboard()
|
||||||
|
{
|
||||||
|
m_backup->Close();
|
||||||
|
delete m_backup;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CEXIBaseboard::SetCS(int cs)
|
void CEXIBaseboard::SetCS(int cs)
|
||||||
{
|
{
|
||||||
|
DEBUG_LOG_FMT(SP1, "AM-BB: ChipSelect={}", cs);
|
||||||
if (cs)
|
if (cs)
|
||||||
m_position = 0;
|
m_position = 0;
|
||||||
}
|
}
|
||||||
|
@ -25,33 +143,199 @@ bool CEXIBaseboard::IsPresent() const
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CEXIBaseboard::TransferByte(u8& byte)
|
bool CEXIBaseboard::IsInterruptSet()
|
||||||
{
|
{
|
||||||
if (m_position == 0)
|
if (g_interrupt_set)
|
||||||
{
|
{
|
||||||
m_command = byte;
|
DEBUG_LOG_FMT(SP1, "AM-BB: IRQ");
|
||||||
|
if (++g_irq_timer > 12)
|
||||||
|
g_interrupt_set = false;
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
switch (m_command)
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CEXIBaseboard::DMAWrite(u32 addr, u32 size)
|
||||||
|
{
|
||||||
|
auto& system = Core::System::GetInstance();
|
||||||
|
auto& memory = system.GetMemory();
|
||||||
|
|
||||||
|
NOTICE_LOG_FMT(SP1, "AM-BB: COMMAND: Backup DMA Write: {:08x} {:x}", addr, size);
|
||||||
|
|
||||||
|
m_backup->Seek(m_backoffset, File::SeekOrigin::Begin);
|
||||||
|
|
||||||
|
m_backup->WriteBytes(memory.GetPointer(addr), size);
|
||||||
|
|
||||||
|
m_backup->Flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CEXIBaseboard::DMARead(u32 addr, u32 size)
|
||||||
|
{
|
||||||
|
auto& system = Core::System::GetInstance();
|
||||||
|
auto& memory = system.GetMemory();
|
||||||
|
|
||||||
|
NOTICE_LOG_FMT(SP1, "AM-BB: COMMAND: Backup DMA Read: {:08x} {:x}", addr, size);
|
||||||
|
|
||||||
|
m_backup->Seek(m_backoffset, File::SeekOrigin::Begin);
|
||||||
|
|
||||||
|
m_backup->Flush();
|
||||||
|
|
||||||
|
m_backup->ReadBytes(memory.GetPointer(addr), size);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CEXIBaseboard::TransferByte(u8& _byte)
|
||||||
|
{
|
||||||
|
DEBUG_LOG_FMT(SP1, "AM-BB: > {:02x}", _byte);
|
||||||
|
if (m_position < 4)
|
||||||
{
|
{
|
||||||
case 0x00:
|
m_command[m_position] = _byte;
|
||||||
|
_byte = 0xFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((m_position >= 2) && (m_command[0] == 0 && m_command[1] == 0))
|
||||||
{
|
{
|
||||||
static constexpr std::array<u8, 4> ID = {0x06, 0x04, 0x10, 0x00};
|
// Read serial ID
|
||||||
byte = ID[(m_position - 2) & 3];
|
_byte = "\x06\x04\x10\x00"[(m_position - 2) & 3];
|
||||||
|
}
|
||||||
|
else if (m_position == 3)
|
||||||
|
{
|
||||||
|
u32 checksum = (m_command[0] << 24) | (m_command[1] << 16) | (m_command[2] << 8);
|
||||||
|
u32 bit = 0x80000000UL;
|
||||||
|
u32 check = 0x8D800000UL;
|
||||||
|
while (bit >= 0x100)
|
||||||
|
{
|
||||||
|
if (checksum & bit)
|
||||||
|
checksum ^= check;
|
||||||
|
check >>= 1;
|
||||||
|
bit >>= 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_command[3] != (checksum & 0xFF))
|
||||||
|
DEBUG_LOG_FMT(SP1, "AM-BB: cs: {:02x}, w: {:02x}", m_command[3], checksum & 0xFF);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (m_position == 4)
|
||||||
|
{
|
||||||
|
switch (m_command[0])
|
||||||
|
{
|
||||||
|
case BackupOffsetSet:
|
||||||
|
m_backoffset = (m_command[1] << 8) | m_command[2];
|
||||||
|
DEBUG_LOG_FMT(SP1, "AM-BB: COMMAND: BackupOffsetSet:{:04x}", m_backoffset);
|
||||||
|
m_backup->Seek(m_backoffset, File::SeekOrigin::Begin);
|
||||||
|
_byte = 0x01;
|
||||||
|
break;
|
||||||
|
case BackupWrite:
|
||||||
|
DEBUG_LOG_FMT(SP1, "AM-BB: COMMAND: BackupWrite:{:04x}-{:02x}", m_backoffset, m_command[1]);
|
||||||
|
m_backup->WriteBytes(&m_command[1], 1);
|
||||||
|
m_backup->Flush();
|
||||||
|
_byte = 0x01;
|
||||||
|
break;
|
||||||
|
case BackupRead:
|
||||||
|
DEBUG_LOG_FMT(SP1, "AM-BB: COMMAND: BackupRead :{:04x}", m_backoffset);
|
||||||
|
_byte = 0x01;
|
||||||
|
break;
|
||||||
|
case DMAOffsetLengthSet:
|
||||||
|
m_backup_dma_offset = (m_command[1] << 8) | m_command[2];
|
||||||
|
m_backup_dma_length = m_command[3];
|
||||||
|
NOTICE_LOG_FMT(SP1, "AM-BB: COMMAND: DMAOffsetLengthSet :{:04x} {:02x}", m_backup_dma_offset,
|
||||||
|
m_backup_dma_length);
|
||||||
|
_byte = 0x01;
|
||||||
|
break;
|
||||||
|
case ReadISR:
|
||||||
|
NOTICE_LOG_FMT(SP1, "AM-BB: COMMAND: ReadISR :{:02x} {:02x}:{:02x} {:02x}", m_command[1],
|
||||||
|
m_command[2], 4, g_irq_status);
|
||||||
|
_byte = 0x04;
|
||||||
|
break;
|
||||||
|
case WriteISR:
|
||||||
|
NOTICE_LOG_FMT(SP1, "AM-BB: COMMAND: WriteISR :{:02x} {:02x}", m_command[1], m_command[2]);
|
||||||
|
g_irq_status &= ~(m_command[2]);
|
||||||
|
_byte = 0x04;
|
||||||
|
break;
|
||||||
|
// 2 byte out
|
||||||
|
case ReadIMR:
|
||||||
|
NOTICE_LOG_FMT(SP1, "AM-BB: COMMAND: ReadIMR :{:02x} {:02x}", m_command[1], m_command[2]);
|
||||||
|
_byte = 0x04;
|
||||||
|
break;
|
||||||
|
case WriteIMR:
|
||||||
|
NOTICE_LOG_FMT(SP1, "AM-BB: COMMAND: WriteIMR :{:02x} {:02x}", m_command[1], m_command[2]);
|
||||||
|
_byte = 0x04;
|
||||||
|
break;
|
||||||
|
case WriteLANCNT:
|
||||||
|
NOTICE_LOG_FMT(SP1, "AM-BB: COMMAND: WriteLANCNT :{:02x} {:02x}", m_command[1],
|
||||||
|
m_command[2]);
|
||||||
|
if ((m_command[1] == 0) && (m_command[2] == 0))
|
||||||
|
{
|
||||||
|
g_interrupt_set = true;
|
||||||
|
g_irq_timer = 0;
|
||||||
|
g_irq_status = 0x02;
|
||||||
|
}
|
||||||
|
if ((m_command[1] == 2) && (m_command[2] == 1))
|
||||||
|
{
|
||||||
|
g_irq_status = 0;
|
||||||
|
}
|
||||||
|
_byte = 0x08;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
_byte = 4;
|
||||||
|
ERROR_LOG_FMT(SP1, "AM-BB: COMMAND: {:02x} {:02x} {:02x}", m_command[0], m_command[1],
|
||||||
|
m_command[2]);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
else if (m_position > 4)
|
||||||
|
{
|
||||||
|
switch (m_command[0])
|
||||||
|
{
|
||||||
|
// 1 byte out
|
||||||
|
case BackupRead:
|
||||||
|
m_backup->Flush();
|
||||||
|
m_backup->ReadBytes(&_byte, 1);
|
||||||
|
break;
|
||||||
|
case DMAOffsetLengthSet:
|
||||||
|
_byte = 0x01;
|
||||||
|
break;
|
||||||
|
// 2 byte out
|
||||||
|
case ReadISR:
|
||||||
|
if (m_position == 6)
|
||||||
|
{
|
||||||
|
_byte = g_irq_status;
|
||||||
|
g_interrupt_set = false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_byte = 0x04;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
// 2 byte out
|
||||||
|
case ReadIMR:
|
||||||
|
if (m_position == 5)
|
||||||
|
_byte = 0xFF;
|
||||||
|
if (m_position == 6)
|
||||||
|
_byte = 0x81;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
ERROR_LOG_FMT(EXPANSIONINTERFACE, "EXI BASEBOARD: Unhandled command {:#x} {:#x}", m_command,
|
ERROR_LOG_FMT(SP1, "Unknown AM-BB command: {:02x}", m_command[0]);
|
||||||
m_position);
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_byte = 0xFF;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
DEBUG_LOG_FMT(SP1, "AM-BB < {:02x}", _byte);
|
||||||
m_position++;
|
m_position++;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CEXIBaseboard::DoState(PointerWrap& p)
|
void CEXIBaseboard::DoState(PointerWrap& p)
|
||||||
{
|
{
|
||||||
p.Do(m_position);
|
p.Do(m_position);
|
||||||
|
p.Do(g_interrupt_set);
|
||||||
p.Do(m_command);
|
p.Do(m_command);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace ExpansionInterface
|
} // namespace ExpansionInterface
|
||||||
|
|
|
@ -1,27 +1,68 @@
|
||||||
// Copyright 2013 Dolphin Emulator Project
|
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "Core/HW/EXI/EXI_Device.h"
|
#include <SFML/Network.hpp>
|
||||||
|
#include <deque>
|
||||||
|
#include <memory>
|
||||||
|
#include <mutex>
|
||||||
|
#include <queue>
|
||||||
|
#include <thread>
|
||||||
|
|
||||||
|
#include "Common/CommonTypes.h"
|
||||||
|
#include "Common/Flag.h"
|
||||||
|
#include "Core/HW/EXI/EXI_Device.h"
|
||||||
|
#include "Common/IOFile.h"
|
||||||
|
|
||||||
|
namespace Core
|
||||||
|
{
|
||||||
|
class System;
|
||||||
|
}
|
||||||
|
|
||||||
class PointerWrap;
|
|
||||||
|
|
||||||
namespace ExpansionInterface
|
namespace ExpansionInterface
|
||||||
{
|
{
|
||||||
|
void GenerateInterrupt(int flag);
|
||||||
|
|
||||||
class CEXIBaseboard : public IEXIDevice
|
class CEXIBaseboard : public IEXIDevice
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
CEXIBaseboard(Core::System& system);
|
explicit CEXIBaseboard(Core::System& system);
|
||||||
void SetCS(int cs) override;
|
virtual ~CEXIBaseboard();
|
||||||
|
|
||||||
|
void SetCS(int _iCS) override;
|
||||||
|
bool IsInterruptSet() override;
|
||||||
bool IsPresent() const override;
|
bool IsPresent() const override;
|
||||||
void DoState(PointerWrap& p) override;
|
void DoState(PointerWrap& p) override;
|
||||||
|
void DMAWrite(u32 addr, u32 size) override;
|
||||||
|
void DMARead(u32 addr, u32 size) override;
|
||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// STATE_TO_SAVE
|
|
||||||
u32 m_position = 0;
|
|
||||||
u32 m_command = 0;
|
|
||||||
|
|
||||||
void TransferByte(u8& byte) override;
|
enum Command
|
||||||
|
{
|
||||||
|
BackupOffsetSet = 0x01,
|
||||||
|
BackupWrite = 0x02,
|
||||||
|
BackupRead = 0x03,
|
||||||
|
|
||||||
|
DMAOffsetLengthSet = 0x05,
|
||||||
|
|
||||||
|
ReadISR = 0x82,
|
||||||
|
WriteISR = 0x83,
|
||||||
|
ReadIMR = 0x86,
|
||||||
|
WriteIMR = 0x87,
|
||||||
|
|
||||||
|
WriteLANCNT = 0xFF,
|
||||||
|
};
|
||||||
|
|
||||||
|
u32 m_position;
|
||||||
|
u32 m_backup_dma_offset;
|
||||||
|
u32 m_backup_dma_length;
|
||||||
|
u8 m_command[4];
|
||||||
|
u16 m_backoffset;
|
||||||
|
File::IOFile* m_backup;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void TransferByte(u8& _uByte) override;
|
||||||
};
|
};
|
||||||
} // namespace ExpansionInterface
|
} // namespace ExpansionInterface
|
||||||
|
|
|
@ -526,6 +526,25 @@ std::span<u8> MemoryManager::GetSpanForAddress(u32 address) const
|
||||||
LR(ppc_state));
|
LR(ppc_state));
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
u8* MemoryManager::GetPointer(u32 address) const
|
||||||
|
{
|
||||||
|
// TODO: Should we be masking off more bits here? Can all devices access
|
||||||
|
// EXRAM?
|
||||||
|
address &= 0x3FFFFFFF;
|
||||||
|
if (address < GetRamSizeReal())
|
||||||
|
return m_ram + address;
|
||||||
|
|
||||||
|
if (m_exram)
|
||||||
|
{
|
||||||
|
if ((address >> 28) == 0x1 && (address & 0x0fffffff) < GetExRamSizeReal())
|
||||||
|
return m_exram + (address & GetExRamMask());
|
||||||
|
}
|
||||||
|
|
||||||
|
auto& ppc_state = m_system.GetPPCState();
|
||||||
|
PanicAlertFmt("Unknown Pointer {:#010x} PC {:#010x} LR {:#010x}", address, ppc_state.pc,
|
||||||
|
LR(ppc_state));
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
u8 MemoryManager::Read_U8(u32 address) const
|
u8 MemoryManager::Read_U8(u32 address) const
|
||||||
{
|
{
|
||||||
|
|
|
@ -115,7 +115,7 @@ public:
|
||||||
// If the specified range is within a single valid memory region, returns a pointer to the start
|
// If the specified range is within a single valid memory region, returns a pointer to the start
|
||||||
// of the corresponding range in host memory. Otherwise, returns nullptr.
|
// of the corresponding range in host memory. Otherwise, returns nullptr.
|
||||||
u8* GetPointerForRange(u32 address, size_t size) const;
|
u8* GetPointerForRange(u32 address, size_t size) const;
|
||||||
|
u8* GetPointer(u32 address) const;
|
||||||
void CopyFromEmu(void* data, u32 address, size_t size) const;
|
void CopyFromEmu(void* data, u32 address, size_t size) const;
|
||||||
void CopyToEmu(u32 address, const void* data, size_t size);
|
void CopyToEmu(u32 address, const void* data, size_t size);
|
||||||
void Memset(u32 address, u8 value, size_t size);
|
void Memset(u32 address, u8 value, size_t size);
|
||||||
|
|
|
@ -56,6 +56,7 @@ public:
|
||||||
void RemoveEvent(int device_number);
|
void RemoveEvent(int device_number);
|
||||||
|
|
||||||
void UpdateDevices();
|
void UpdateDevices();
|
||||||
|
u32 GetInLength(void) const { return m_com_csr.INLNGTH; }
|
||||||
|
|
||||||
void RemoveDevice(int device_number);
|
void RemoveDevice(int device_number);
|
||||||
void AddDevice(SIDevices device, int device_number);
|
void AddDevice(SIDevices device, int device_number);
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
#include "Core/HW/SI/SI_DeviceGCController.h"
|
#include "Core/HW/SI/SI_DeviceGCController.h"
|
||||||
#include "Core/HW/SI/SI_DeviceGCSteeringWheel.h"
|
#include "Core/HW/SI/SI_DeviceGCSteeringWheel.h"
|
||||||
#include "Core/HW/SI/SI_DeviceKeyboard.h"
|
#include "Core/HW/SI/SI_DeviceKeyboard.h"
|
||||||
|
#include "Core/HW/SI/SI_DeviceAMBaseboard.h"
|
||||||
#include "Core/HW/SI/SI_DeviceNull.h"
|
#include "Core/HW/SI/SI_DeviceNull.h"
|
||||||
#include "Core/HW/SystemTimers.h"
|
#include "Core/HW/SystemTimers.h"
|
||||||
#include "Core/System.h"
|
#include "Core/System.h"
|
||||||
|
@ -181,6 +182,8 @@ std::unique_ptr<ISIDevice> SIDevice_Create(Core::System& system, const SIDevices
|
||||||
return std::make_unique<CSIDevice_Keyboard>(system, device, port_number);
|
return std::make_unique<CSIDevice_Keyboard>(system, device, port_number);
|
||||||
|
|
||||||
case SIDEVICE_AM_BASEBOARD:
|
case SIDEVICE_AM_BASEBOARD:
|
||||||
|
return std::make_unique<CSIDevice_AMBaseboard>(system, device, port_number);
|
||||||
|
|
||||||
case SIDEVICE_NONE:
|
case SIDEVICE_NONE:
|
||||||
default:
|
default:
|
||||||
return std::make_unique<CSIDevice_Null>(system, device, port_number);
|
return std::make_unique<CSIDevice_Null>(system, device, port_number);
|
||||||
|
|
|
@ -97,8 +97,6 @@ enum SIDevices : int
|
||||||
SIDEVICE_GC_STEERING,
|
SIDEVICE_GC_STEERING,
|
||||||
SIDEVICE_DANCEMAT,
|
SIDEVICE_DANCEMAT,
|
||||||
SIDEVICE_GC_TARUKONGA,
|
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_AM_BASEBOARD,
|
||||||
SIDEVICE_WIIU_ADAPTER,
|
SIDEVICE_WIIU_ADAPTER,
|
||||||
SIDEVICE_GC_GBA_EMULATED,
|
SIDEVICE_GC_GBA_EMULATED,
|
||||||
|
|
2192
Source/Core/Core/HW/SI/SI_DeviceAMBaseboard.cpp
Normal file
2192
Source/Core/Core/HW/SI/SI_DeviceAMBaseboard.cpp
Normal file
File diff suppressed because it is too large
Load diff
254
Source/Core/Core/HW/SI/SI_DeviceAMBaseboard.h
Normal file
254
Source/Core/Core/HW/SI/SI_DeviceAMBaseboard.h
Normal file
|
@ -0,0 +1,254 @@
|
||||||
|
// Copyright 2017 Dolphin Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <SFML/Network.hpp>
|
||||||
|
#include <deque>
|
||||||
|
#include <memory>
|
||||||
|
#include <mutex>
|
||||||
|
#include <queue>
|
||||||
|
#include <thread>
|
||||||
|
|
||||||
|
#include "Common/CommonTypes.h"
|
||||||
|
#include "Common/Flag.h"
|
||||||
|
#include "Core/HW/SI/SI_Device.h"
|
||||||
|
|
||||||
|
namespace SerialInterface
|
||||||
|
{
|
||||||
|
|
||||||
|
// "JAMMA Video Standard" I/O
|
||||||
|
class JVSIOMessage
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
u32 m_ptr, m_last_start, m_csum;
|
||||||
|
u8 m_msg[0x80];
|
||||||
|
|
||||||
|
JVSIOMessage();
|
||||||
|
void start(int node);
|
||||||
|
void addData(const u8* dst, size_t len, int sync);
|
||||||
|
void addData(const void* data, size_t len);
|
||||||
|
void addData(const char* data);
|
||||||
|
void addData(u32 n);
|
||||||
|
void end();
|
||||||
|
}; // end class JVSIOMessage
|
||||||
|
|
||||||
|
// triforce (GC-AM) baseboard
|
||||||
|
class CSIDevice_AMBaseboard : public ISIDevice
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
enum BaseBoardCommand
|
||||||
|
{
|
||||||
|
GCAM_Reset = 0x00,
|
||||||
|
GCAM_Command = 0x70,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum GCAMCommand
|
||||||
|
{
|
||||||
|
StatusSwitches = 0x10,
|
||||||
|
SerialNumber = 0x11,
|
||||||
|
Unknown_12 = 0x12,
|
||||||
|
Unknown_14 = 0x14,
|
||||||
|
FirmVersion= 0x15,
|
||||||
|
FPGAVersion= 0x16,
|
||||||
|
RegionSettings = 0x1F,
|
||||||
|
|
||||||
|
Unknown_21 = 0x21,
|
||||||
|
Unknown_22 = 0x22,
|
||||||
|
Unknown_23 = 0x23,
|
||||||
|
Unknown_24 = 0x24,
|
||||||
|
|
||||||
|
SerialA = 0x31,
|
||||||
|
SerialB = 0x32,
|
||||||
|
|
||||||
|
JVSIOA = 0x40,
|
||||||
|
JVSIOB = 0x41,
|
||||||
|
|
||||||
|
Unknown_60 = 0x60,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum JVSIOCommand
|
||||||
|
{
|
||||||
|
IOID = 0x10,
|
||||||
|
CommandRevision = 0x11,
|
||||||
|
JVRevision = 0x12,
|
||||||
|
CommunicationVersion = 0x13,
|
||||||
|
CheckFunctionality = 0x14,
|
||||||
|
MainID = 0x15,
|
||||||
|
|
||||||
|
SwitchesInput = 0x20,
|
||||||
|
CoinInput = 0x21,
|
||||||
|
AnalogInput = 0x22,
|
||||||
|
RotaryInput = 0x23,
|
||||||
|
KeyCodeInput = 0x24,
|
||||||
|
PositionInput = 0x25,
|
||||||
|
GeneralSwitchInput = 0x26,
|
||||||
|
|
||||||
|
PayoutRemain = 0x2E,
|
||||||
|
Retrans = 0x2F,
|
||||||
|
CoinSubOutput = 0x30,
|
||||||
|
PayoutAddOutput = 0x31,
|
||||||
|
GeneralDriverOutput = 0x32,
|
||||||
|
AnalogOutput = 0x33,
|
||||||
|
CharacterOutput = 0x34,
|
||||||
|
CoinAddOutput = 0x35,
|
||||||
|
PayoutSubOutput = 0x36,
|
||||||
|
GeneralDriverOutput2 = 0x37,
|
||||||
|
GeneralDriverOutput3 = 0x38,
|
||||||
|
|
||||||
|
NAMCOCommand = 0x70,
|
||||||
|
|
||||||
|
Reset = 0xF0,
|
||||||
|
SetAddress = 0xF1,
|
||||||
|
ChangeComm = 0xF2,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum JVSIOStatusCode
|
||||||
|
{
|
||||||
|
StatusOkay = 1,
|
||||||
|
UnsupportedCommand = 2,
|
||||||
|
ChecksumError = 3,
|
||||||
|
AcknowledgeOverflow = 4,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum CARDCommand
|
||||||
|
{
|
||||||
|
Init = 0x10,
|
||||||
|
GetState = 0x20,
|
||||||
|
Read = 0x33,
|
||||||
|
IsPresent = 0x40,
|
||||||
|
Write = 0x53,
|
||||||
|
SetPrintParam = 0x78,
|
||||||
|
RegisterFont = 0x7A,
|
||||||
|
WriteInfo = 0x7C,
|
||||||
|
Erase = 0x7D,
|
||||||
|
Eject = 0x80,
|
||||||
|
Clean = 0xA0,
|
||||||
|
Load = 0xB0,
|
||||||
|
SetShutter = 0xD0,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum ICCARDCommand
|
||||||
|
{
|
||||||
|
GetStatus = 0x10,
|
||||||
|
SetBaudrate = 0x11,
|
||||||
|
FieldOn = 0x14,
|
||||||
|
FieldOff = 0x15,
|
||||||
|
InsertCheck = 0x20,
|
||||||
|
AntiCollision = 0x21,
|
||||||
|
SelectCard = 0x22,
|
||||||
|
ReadPage = 0x24,
|
||||||
|
WritePage = 0x25,
|
||||||
|
DecreaseUseCount = 0x26,
|
||||||
|
ReadUseCount = 0x33,
|
||||||
|
ReadPages = 0x34,
|
||||||
|
WritePages = 0x35,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum CDReaderCommand
|
||||||
|
{
|
||||||
|
ShutterAuto = 0x61,
|
||||||
|
BootVersion = 0x62,
|
||||||
|
SensLock = 0x63,
|
||||||
|
SensCard = 0x65,
|
||||||
|
FirmwareUpdate =0x66,
|
||||||
|
ShutterGet = 0x67,
|
||||||
|
CameraCheck = 0x68,
|
||||||
|
ShutterCard = 0x69,
|
||||||
|
ProgramChecksum = 0x6B,
|
||||||
|
BootChecksum = 0x6D,
|
||||||
|
ShutterLoad = 0x6F,
|
||||||
|
ReadCard = 0x72,
|
||||||
|
ShutterSave = 0x73,
|
||||||
|
SelfTest = 0x74,
|
||||||
|
ProgramVersion = 0x76,
|
||||||
|
};
|
||||||
|
|
||||||
|
union ICCommand
|
||||||
|
{
|
||||||
|
u8 data[81 + 4 + 4 + 4];
|
||||||
|
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
u32 pktcmd : 8;
|
||||||
|
u32 pktlen : 8;
|
||||||
|
u32 fixed : 8;
|
||||||
|
u32 command : 8;
|
||||||
|
u32 flag : 8;
|
||||||
|
u32 length : 8;
|
||||||
|
u32 status : 16;
|
||||||
|
|
||||||
|
u8 extdata[81];
|
||||||
|
u32 extlen;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
u16 m_coin[2];
|
||||||
|
u32 m_coin_pressed[2];
|
||||||
|
|
||||||
|
u8 m_ic_card_data[2048];
|
||||||
|
u16 m_ic_card_state;
|
||||||
|
/*
|
||||||
|
0 - OK
|
||||||
|
8000 - no card
|
||||||
|
800E - ???
|
||||||
|
other- bad card
|
||||||
|
*/
|
||||||
|
u16 m_ic_card_status;
|
||||||
|
u16 m_ic_card_session;
|
||||||
|
u8 m_ic_write_buffer[512];
|
||||||
|
u32 m_ic_write_offset;
|
||||||
|
u32 m_ic_write_size;
|
||||||
|
|
||||||
|
u8 m_card_memory[0xD0];
|
||||||
|
u8 m_card_read_packet[0xDB];
|
||||||
|
u8 m_card_buffer[0x100];
|
||||||
|
u32 m_card_memory_size;
|
||||||
|
u32 m_card_is_inserted;
|
||||||
|
u32 m_card_command;
|
||||||
|
u32 m_card_clean;
|
||||||
|
u32 m_card_write_length;
|
||||||
|
u32 m_card_wrote;
|
||||||
|
u32 m_card_read_length;
|
||||||
|
u32 m_card_read;
|
||||||
|
u32 m_card_bit;
|
||||||
|
u32 m_card_shutter;
|
||||||
|
u32 m_card_state_call_count;
|
||||||
|
u8 m_card_offset;
|
||||||
|
|
||||||
|
u32 m_wheelinit;
|
||||||
|
|
||||||
|
u32 m_motorinit;
|
||||||
|
u8 m_motorreply[64];
|
||||||
|
s16 m_motorforce_x;
|
||||||
|
|
||||||
|
// F-Zero AX (DX)
|
||||||
|
u32 m_fzdx_seatbelt;
|
||||||
|
u32 m_fzdx_motion_stop;
|
||||||
|
u32 m_fzdx_sensor_right;
|
||||||
|
u32 m_fzdx_sensor_left;
|
||||||
|
u8 m_rx_reply;
|
||||||
|
|
||||||
|
// F-Zero AX (CryCraft)
|
||||||
|
u32 m_fzcc_seatbelt;
|
||||||
|
u32 m_fzcc_sensor;
|
||||||
|
u32 m_fzcc_emergency;
|
||||||
|
u32 m_fzcc_service;
|
||||||
|
|
||||||
|
void ICCardSendReply(ICCommand* iccommand, u8* buffer, u32* length);
|
||||||
|
|
||||||
|
public:
|
||||||
|
// constructor
|
||||||
|
CSIDevice_AMBaseboard(Core::System& system, SIDevices device, int device_number);
|
||||||
|
|
||||||
|
// run the SI Buffer
|
||||||
|
int RunBuffer(u8* buffer, int request_length) override;
|
||||||
|
|
||||||
|
// return true on new data
|
||||||
|
DataResponse GetData(u32& hi, u32& low) override;
|
||||||
|
|
||||||
|
// send a command directly
|
||||||
|
void SendCommand(u32 command, u8 poll) override;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace SerialInterface
|
|
@ -70,20 +70,24 @@
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Text Include="$(BuildInfoTemplate)" />
|
<Text Include="$(BuildInfoTemplate)" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<UsingTask TaskName="GetProductVersion"
|
<ItemGroup>
|
||||||
TaskFactory="CodeTaskFactory"
|
<ClCompile Include="Core\HW\DVD\AMMediaboard.cpp" />
|
||||||
AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.Core.dll">
|
<ClCompile Include="Core\HW\SI\SI_DeviceAMBaseboard.cpp" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClInclude Include="Core\HW\DVD\AMMediaboard.h" />
|
||||||
|
<ClInclude Include="Core\HW\SI\SI_DeviceAMBaseboard.h" />
|
||||||
|
</ItemGroup>
|
||||||
|
<UsingTask TaskName="GetProductVersion" TaskFactory="CodeTaskFactory" AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.Core.dll">
|
||||||
<ParameterGroup>
|
<ParameterGroup>
|
||||||
<Path ParameterType="System.String" Required="true" />
|
<Path ParameterType="System.String" Required="true" />
|
||||||
<ProductVersion ParameterType="System.String" Output="true" />
|
<ProductVersion ParameterType="System.String" Output="true" />
|
||||||
</ParameterGroup>
|
</ParameterGroup>
|
||||||
<Task>
|
<Task>
|
||||||
<Using Namespace="System.Diagnostics"/>
|
<Using Namespace="System.Diagnostics" />
|
||||||
<Code Type="Fragment" Language="cs">
|
<Code Type="Fragment" Language="cs"><![CDATA[
|
||||||
<![CDATA[
|
|
||||||
ProductVersion = FileVersionInfo.GetVersionInfo(Path).ProductVersion;
|
ProductVersion = FileVersionInfo.GetVersionInfo(Path).ProductVersion;
|
||||||
]]>
|
]]></Code>
|
||||||
</Code>
|
|
||||||
</Task>
|
</Task>
|
||||||
</UsingTask>
|
</UsingTask>
|
||||||
<Target Name="WriteBuildInfo" AfterTargets="Build" Inputs="$(BuildInfoTemplate)" Outputs="$(BuildInfoOutput)">
|
<Target Name="WriteBuildInfo" AfterTargets="Build" Inputs="$(BuildInfoTemplate)" Outputs="$(BuildInfoOutput)">
|
||||||
|
@ -91,10 +95,6 @@
|
||||||
<Output PropertyName="VCToolsProductVersion" TaskParameter="ProductVersion" />
|
<Output PropertyName="VCToolsProductVersion" TaskParameter="ProductVersion" />
|
||||||
</GetProductVersion>
|
</GetProductVersion>
|
||||||
<Message Text="VCToolsProductVersion $(VCToolsProductVersion)" Importance="High" />
|
<Message Text="VCToolsProductVersion $(VCToolsProductVersion)" Importance="High" />
|
||||||
<WriteLinesToFile
|
<WriteLinesToFile File="$(BuildInfoOutput)" Lines="$([System.IO.File]::ReadAllText($(BuildInfoTemplate)).Replace('${VC_TOOLS_VERSION}', $(VCToolsProductVersion)))" Overwrite="true" />
|
||||||
File="$(BuildInfoOutput)"
|
|
||||||
Lines="$([System.IO.File]::ReadAllText($(BuildInfoTemplate)).Replace('${VC_TOOLS_VERSION}', $(VCToolsProductVersion)))"
|
|
||||||
Overwrite="true"
|
|
||||||
/>
|
|
||||||
</Target>
|
</Target>
|
||||||
</Project>
|
</Project>
|
|
@ -43,6 +43,7 @@ static constexpr std::array s_gc_types = {
|
||||||
#endif
|
#endif
|
||||||
SIDeviceName{SerialInterface::SIDEVICE_GC_GBA, _trans("GBA (TCP)")},
|
SIDeviceName{SerialInterface::SIDEVICE_GC_GBA, _trans("GBA (TCP)")},
|
||||||
SIDeviceName{SerialInterface::SIDEVICE_GC_KEYBOARD, _trans("Keyboard Controller")},
|
SIDeviceName{SerialInterface::SIDEVICE_GC_KEYBOARD, _trans("Keyboard Controller")},
|
||||||
|
SIDeviceName{SerialInterface::SIDEVICE_AM_BASEBOARD, _trans("Triforce Baseboard")},
|
||||||
};
|
};
|
||||||
|
|
||||||
static std::optional<int> ToGCMenuIndex(const SerialInterface::SIDevices sidevice)
|
static std::optional<int> ToGCMenuIndex(const SerialInterface::SIDevices sidevice)
|
||||||
|
@ -133,6 +134,7 @@ void GamecubeControllersWidget::OnGCPadConfigure(size_t index)
|
||||||
case SerialInterface::SIDEVICE_NONE:
|
case SerialInterface::SIDEVICE_NONE:
|
||||||
case SerialInterface::SIDEVICE_GC_GBA:
|
case SerialInterface::SIDEVICE_GC_GBA:
|
||||||
return;
|
return;
|
||||||
|
case SerialInterface::SIDEVICE_AM_BASEBOARD:
|
||||||
case SerialInterface::SIDEVICE_GC_CONTROLLER:
|
case SerialInterface::SIDEVICE_GC_CONTROLLER:
|
||||||
type = MappingWindow::Type::MAPPING_GCPAD;
|
type = MappingWindow::Type::MAPPING_GCPAD;
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -146,6 +146,7 @@ void GameCubePane::CreateWidgets()
|
||||||
EXIDeviceType::EthernetTapServer,
|
EXIDeviceType::EthernetTapServer,
|
||||||
EXIDeviceType::EthernetBuiltIn,
|
EXIDeviceType::EthernetBuiltIn,
|
||||||
EXIDeviceType::ModemTapServer,
|
EXIDeviceType::ModemTapServer,
|
||||||
|
EXIDeviceType::Baseboard
|
||||||
})
|
})
|
||||||
{
|
{
|
||||||
m_slot_combos[ExpansionInterface::Slot::SP1]->addItem(tr(fmt::format("{:n}", device).c_str()),
|
m_slot_combos[ExpansionInterface::Slot::SP1]->addItem(tr(fmt::format("{:n}", device).c_str()),
|
||||||
|
@ -414,6 +415,10 @@ void GameCubePane::OnConfigPressed(ExpansionInterface::Slot slot)
|
||||||
dialog.exec();
|
dialog.exec();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
case ExpansionInterface::EXIDeviceType::Baseboard:
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
PanicAlertFmt("Unknown settings pressed for {}", device);
|
PanicAlertFmt("Unknown settings pressed for {}", device);
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -269,6 +269,7 @@ void CreateDirectories()
|
||||||
File::CreateFullPath(File::GetUserPath(D_GCUSER_IDX) + USA_DIR DIR_SEP);
|
File::CreateFullPath(File::GetUserPath(D_GCUSER_IDX) + USA_DIR DIR_SEP);
|
||||||
File::CreateFullPath(File::GetUserPath(D_GCUSER_IDX) + EUR_DIR DIR_SEP);
|
File::CreateFullPath(File::GetUserPath(D_GCUSER_IDX) + EUR_DIR DIR_SEP);
|
||||||
File::CreateFullPath(File::GetUserPath(D_GCUSER_IDX) + JAP_DIR DIR_SEP);
|
File::CreateFullPath(File::GetUserPath(D_GCUSER_IDX) + JAP_DIR DIR_SEP);
|
||||||
|
File::CreateFullPath(File::GetUserPath(D_TRIUSER_IDX));
|
||||||
File::CreateFullPath(File::GetUserPath(D_HIRESTEXTURES_IDX));
|
File::CreateFullPath(File::GetUserPath(D_HIRESTEXTURES_IDX));
|
||||||
File::CreateFullPath(File::GetUserPath(D_GRAPHICSMOD_IDX));
|
File::CreateFullPath(File::GetUserPath(D_GRAPHICSMOD_IDX));
|
||||||
File::CreateFullPath(File::GetUserPath(D_MAILLOGS_IDX));
|
File::CreateFullPath(File::GetUserPath(D_MAILLOGS_IDX));
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue