Fixed emulated Nunchuck in Mario Galaxy and Wii Sports

git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@1222 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
John Peterson 2008-11-20 08:46:16 +00:00
parent aabee66444
commit 5fb23f879e
14 changed files with 328 additions and 366 deletions

View File

@ -944,7 +944,7 @@ namespace Core
{
LOGV(WII_IPC_WIIMOTE, 3, "=========================================================");
const u8* pData = (const u8*)_pData;
LOGV(WII_IPC_WIIMOTE, 3, "Callback_WiimoteInput: 0x%x", _channelID);
LOGV(WII_IPC_WIIMOTE, 3, "Callback_WiimoteInput:");
std::string Temp;
for (u32 j=0; j<_Size; j++)
{
@ -953,6 +953,7 @@ namespace Core
Temp.append(Buffer);
}
LOGV(WII_IPC_WIIMOTE, 3, " Data: %s", Temp.c_str());
//LOGV(WII_IPC_WIIMOTE, 3, " Channel: %s", _channelID);
s_Usb->m_WiiMotes[0].SendL2capData(_channelID, _pData, _Size);
LOGV(WII_IPC_WIIMOTE, 3, "=========================================================");

View File

@ -142,7 +142,7 @@ bool BootCore(const std::string& _rFilename)
}
else
{
PanicAlert("Could not write to SYSCONF");
PanicAlert("Could not read %sSYSCONF", FULL_CONFIG_DIR);
}
// ----------------
}

View File

@ -72,7 +72,7 @@ CConfigMain::CConfigMain(wxWindow* parent, wxWindowID id, const wxString& title,
}
else
{
PanicAlert("Could not read Wii SYSCONF");
PanicAlert("Could not read " FULL_CONFIG_DIR "SYSCONF");
}
CreateGUIControls();

View File

@ -128,7 +128,7 @@ int aprintf(int a, char *fmt, ...)
// Printf to screen function
int wprintf(char *fmt, ...)
{
#if defined(DEBUG_HLE) && defined(_WIN32)
#if defined(DEBUG_HLE) && defined(_WIN32) && (defined(_DEBUG) || defined(DEBUGFAST))
char s[1024*20]; // Warning, mind this value
va_list argptr;
int cnt;

View File

@ -576,6 +576,10 @@
RelativePath=".\Src\FillReport.cpp"
>
</File>
<File
RelativePath=".\Src\wiimote_hid.h"
>
</File>
</Filter>
<Filter
Name="Real Wiimote"
@ -613,10 +617,6 @@
RelativePath=".\Src\main.cpp"
>
</File>
<File
RelativePath=".\Src\wiimote_hid.h"
>
</File>
</Files>
<Globals>
</Globals>

View File

@ -131,9 +131,10 @@ void ConfigDialog::GeneralSettingsChanged(wxCommandEvent& event)
g_Config.bExtensionConnected = m_ExtensionConnected->IsChecked();
// generate connect/disconnect status event
u8 DataFrame[8]; // make a blank report for it
wm_request_status *rs = (wm_request_status*)DataFrame;
if(WiiMoteEmu::g_ReportingChannel > 0)
WiiMoteEmu::WmRequestStatus_(WiiMoteEmu::g_ReportingChannel,
g_Config.bExtensionConnected ? 1 : 0);
WiiMoteEmu::WmRequestStatus(WiiMoteEmu::g_ReportingChannel, rs);
break;
}
}

View File

@ -16,6 +16,24 @@
// http://code.google.com/p/dolphin-emu/
// ===================================================
/* Data reports guide. The different structures location in the Input reports. The ? in
the IR coordinates is the High coordinates that are four in one byte. */
// ----------------
/* 0x33
[c.left etc] [c.a etc] acc.x y z ir0.x y ? ir1.x y ? ir2.x y ? ir3.x y ?
0x37
[c.left etc] [c.a etc] acc.x y z ir0.x1 y1 ? x2 y2 ir1.x1 y1 ? x2 y2 ext.jx jy ax ay az bt*/
// ================
#include "pluginspecs_wiimote.h"
#include <vector>
@ -50,7 +68,6 @@ void WmDataReporting(u16 _channelID, wm_data_reporting* dr)
LOG(WII_IPC_WIIMOTE, " All The Time: %x (not only on data change)", dr->all_the_time);
LOG(WII_IPC_WIIMOTE, " Rumble: %x", dr->rumble);
LOG(WII_IPC_WIIMOTE, " Mode: 0x%02x", dr->mode);
//PanicAlert("Data reporting mode: 0x%02x", dr->mode);
wprintf("\nData reporting mode: 0x%02x", dr->mode);
wprintf("\nData reporting channel: 0x%04x\n", _channelID);
@ -112,6 +129,18 @@ void SendReportCoreAccel(u16 _channelID)
LOGV(WII_IPC_WIIMOTE, 2, " SendReportCoreAccel()");
// Debugging
/*if(GetAsyncKeyState('V'))
{
wprintf("DataFrame: ");
for (int i = 0; i < Offset; i++)
{
wprintf("%02x ", DataFrame[i]);
if((i + 1) % 30 == 0) wprintf("\n");
}
wprintf("\n");
}*/
g_WiimoteInitialize.pWiimoteInput(_channelID, DataFrame, Offset);
}
@ -129,6 +158,8 @@ void SendReportCoreAccelIr12(u16 _channelID) {
FillReportInfo(pReport->c);
FillReportAcc(pReport->a);
// We settle with emulating two objects, not all four
FillReportIR(pReport->ir[0], pReport->ir[1]);
LOGV(WII_IPC_WIIMOTE, 2, " SendReportCoreAccelIr12()");
@ -136,7 +167,7 @@ void SendReportCoreAccelIr12(u16 _channelID) {
// Debugging
#ifdef _WIN32
if(GetAsyncKeyState('V'))
/*if(GetAsyncKeyState('V'))
{
wprintf("DataFrame: ");
for (int i = 0; i < Offset; i++)
@ -145,7 +176,7 @@ void SendReportCoreAccelIr12(u16 _channelID) {
if((i + 1) % 30 == 0) wprintf("\n");
}
wprintf("\n");
}
}*/
#endif
g_WiimoteInitialize.pWiimoteInput(_channelID, DataFrame, Offset);
}
@ -174,7 +205,7 @@ void SendReportCoreAccelExt16(u16 _channelID)
// Debugging
#ifdef _WIN32
if(GetAsyncKeyState('V'))
/*if(GetAsyncKeyState('V'))
{
wprintf("DataFrame: ");
for (int i = 0; i < Offset; i++)
@ -183,7 +214,7 @@ void SendReportCoreAccelExt16(u16 _channelID)
if((i + 1) % 30 == 0) wprintf("\n");
}
wprintf("\n");
}
}*/
#endif
g_WiimoteInitialize.pWiimoteInput(_channelID, DataFrame, Offset);
}
@ -210,7 +241,7 @@ void SendReportCoreAccelIr10Ext(u16 _channelID)
// Debugging
#ifdef _WIN32
if(GetAsyncKeyState('V'))
/*if(GetAsyncKeyState('V'))
{
wprintf("DataFrame: ");
for (int i = 0; i < Offset; i++)
@ -219,7 +250,7 @@ void SendReportCoreAccelIr10Ext(u16 _channelID)
if((i + 1) % 30 == 0) wprintf("\n");
}
wprintf("\n");
}
}*/
#endif
g_WiimoteInitialize.pWiimoteInput(_channelID, DataFrame, Offset);
}

View File

@ -29,8 +29,6 @@
#include "Console.h" // for startConsoleWin, wprintf, GetConsoleHwnd
extern SWiimoteInitialize g_WiimoteInitialize;
//extern void __Log(int log, const char *format, ...);
//extern void __Log(int log, int v, const char *format, ...);
namespace WiiMoteEmu
{
@ -46,7 +44,6 @@ u8 g_Eeprom[WIIMOTE_EEPROM_SIZE];
u8 g_RegSpeaker[WIIMOTE_REG_SPEAKER_SIZE];
u8 g_RegExt[WIIMOTE_REG_EXT_SIZE];
u8 g_RegExtTmp[WIIMOTE_REG_EXT_SIZE];
u8 g_RegExtBlnk[WIIMOTE_REG_EXT_SIZE];
u8 g_RegIr[WIIMOTE_REG_IR_SIZE];
u8 g_ReportingMode; // the reporting mode and channel id

View File

@ -24,6 +24,7 @@
#include "wiimote_hid.h"
#include "EmuSubroutines.h"
#include "EmuDefinitions.h"
#include "EmuMain.h"
#include "Encryption.h" // for extension encryption
#include "Console.h" // for startConsoleWin, wprintf, GetConsoleHwnd
#include "Config.h" // for g_Config
@ -41,20 +42,21 @@ namespace WiiMoteEmu
//******************************************************************************
//wm_request_status global_struct;
//extern wm_request_status global_struct;
// ===================================================
/* Here we process the Output Reports that the Wii sends. Our response will be an Input Report
back to the Wii. Input and Output is from the Wii's perspective, Output means data to
the Wiimote (from the Wii), Input means data from the Wiimote. */
the Wiimote (from the Wii), Input means data from the Wiimote.
The call browser:
1. Wiimote_InterruptChannel > InterruptChannel > HidOutputReport
2. Wiimote_ControlChannel > ControlChannel > HidOutputReport */
// ----------------
void HidOutputReport(u16 _channelID, wm_report* sr) {
LOGV(WII_IPC_WIIMOTE, 0, "===========================================================");
LOGV(WII_IPC_WIIMOTE, 0, "HidOutputReport(0x%02x)", sr->channel);
LOGV(WII_IPC_WIIMOTE, 0, "HidOutputReport (0x%02x)", sr->channel);
switch(sr->channel)
{
@ -95,6 +97,23 @@ void HidOutputReport(u16 _channelID, wm_report* sr) {
}
// ===================================================
/* Generate the right address for wm reports. */
// ----------------
int WriteWmReport(u8* dst, u8 channel) {
u32 Offset = 0;
hid_packet* pHidHeader = (hid_packet*)(dst + Offset);
Offset += sizeof(hid_packet);
pHidHeader->type = HID_TYPE_DATA;
pHidHeader->param = HID_PARAM_INPUT;
wm_report* pReport = (wm_report*)(dst + Offset);
Offset += sizeof(wm_report);
pReport->channel = channel;
return Offset;
}
// ===================================================
/* LED (blue lights) report. */
// ----------------
@ -110,13 +129,18 @@ void WmLeds(u16 _channelID, wm_leds* leds) {
}
void WmSendAck(u16 _channelID, u8 _reportID)
// ===================================================
/* This will generate the 0x22 acknowledgment after all Input reports. It will
have the form a1 22 00 00 _reportID 00. The first two bytes are unknown but
00 00 seems to work fine. */
// ----------------
void WmSendAck(u16 _channelID, u8 _reportID, u32 address)
{
u8 DataFrame[1024];
u32 Offset = 0;
// header
// Header
hid_packet* pHidHeader = (hid_packet*)(DataFrame + Offset);
pHidHeader->type = HID_TYPE_DATA;
pHidHeader->param = HID_PARAM_INPUT;
@ -130,8 +154,22 @@ void WmSendAck(u16 _channelID, u8 _reportID)
pData->errorID = 0;
Offset += sizeof(wm_acknowledge);
/* Debug. Write the report for extension registry writes.
if((_reportID == 0x16 || _reportID == 0x17) && ((address >> 16) & 0xfe) == 0xa4)
{
wprintf("\nWMSendAck Report ID: %02x KeyReady: %i, Encryption: %02x\n",
_reportID, (int)KeyReady, g_RegExt[0xf0]);
wprintf("Data: ");
for (int i = 0; i < Offset; i++)
{
wprintf("%02x ", DataFrame[i]);
if((i + 1) % 20 == 0) wprintf("\n");
}
wprintf("\n");
}*/
LOGV(WII_IPC_WIIMOTE, 2, " WMSendAck()");
LOGV(WII_IPC_WIIMOTE, 2, " Report ID: %02x", _reportID);
g_WiimoteInitialize.pWiimoteInput(_channelID, DataFrame, Offset);
}
@ -151,6 +189,8 @@ void WmReadData(u16 _channelID, wm_read_data* rd)
LOG(WII_IPC_WIIMOTE, " Size: 0x%04x", size);
LOG(WII_IPC_WIIMOTE, " Rumble: %x", rd->rumble);
//u32 _address = address;
if(rd->space == 0)
{
if (address + size > WIIMOTE_EEPROM_SIZE)
@ -218,7 +258,7 @@ void WmReadData(u16 _channelID, wm_read_data* rd)
// Encrypt the read
wiimote_encrypt(&g_ExtKey, &g_RegExtTmp[address & 0xffff], (address & 0xffff), (u8)size);
// Debugging
/* Debugging
wprintf("\nEncrypted data:\n");
for (int i = 0; i < (u8)size; i++)
{
@ -226,16 +266,16 @@ void WmReadData(u16 _channelID, wm_read_data* rd)
if((i + 1) % 20 == 0) wprintf("\n");
}
//wprintf("\ng_RegExtTmp after: \n");
//ReadExtTmp();
//wprintf("\nFrom g_RegExt: \n");
//ReadExt();
wprintf("\ng_RegExtTmp after: \n");
ReadExtTmp();
wprintf("\nFrom g_RegExt: \n");
ReadExt();*/
// Update the block that SendReadDataReply will eventually send to the Wii
block = g_RegExtTmp;
}
wprintf("\n\n\n");
//wprintf("\n\n");
}
//---------
@ -246,14 +286,17 @@ void WmReadData(u16 _channelID, wm_read_data* rd)
return;
}
// Let this function process the message and send it to the Wii
SendReadDataReply(_channelID, block+address, address, (u8)size);
}
else
{
PanicAlert("WmReadData: unimplemented parameters (size: %i, addr: 0x%x!", size, rd->space);
}
// Acknowledge the 0x17 read, we will do this from InterruptChannel()
//WmSendAck(_channelID, WM_READ_DATA, _address);
LOGV(WII_IPC_WIIMOTE, 0, "===========================================================");
}
@ -265,13 +308,15 @@ void WmReadData(u16 _channelID, wm_read_data* rd)
void WmWriteData(u16 _channelID, wm_write_data* wd)
{
LOGV(WII_IPC_WIIMOTE, 0, "========================================================");
u32 address = convert24bit(wd->address);
u32 address = convert24bit(wd->address);
LOG(WII_IPC_WIIMOTE, " Write data");
LOG(WII_IPC_WIIMOTE, " Address space: %x", wd->space);
LOG(WII_IPC_WIIMOTE, " Address: 0x%06x", address);
LOG(WII_IPC_WIIMOTE, " Size: 0x%02x", wd->size);
LOG(WII_IPC_WIIMOTE, " Rumble: %x", wd->rumble);
u32 _address = address;
// Write to EEPROM
if(wd->size <= 16 && wd->space == WM_SPACE_EEPROM)
{
@ -316,7 +361,7 @@ void WmWriteData(u16 _channelID, wm_write_data* wd)
// Remove for example 0xa40000 from the address
address &= 0xFFFF;
_address = address; address &= 0xFFFF;
// Check if the address is within bounds
if(address + wd->size > blockSize) {
@ -332,8 +377,7 @@ void WmWriteData(u16 _channelID, wm_write_data* wd)
// -------------
if(blockSize == WIIMOTE_REG_EXT_SIZE)
{
// Debugging
// Write the data
/* Debugging. Write the data.
wprintf("Data: ");
for (int i = 0; i < wd->size; i++)
{
@ -345,16 +389,14 @@ void WmWriteData(u16 _channelID, wm_write_data* wd)
//wprintf("Current address: %08x\n", address);
//wprintf("g_RegExt:\n");
//ReadExt();
//ReadExt(); */
/* Run the key generation on all writes in the key area, it doesn't matter
that we send it parts of a key, only the last full key will have an
effect */
//if(address >= 0xa40040 && address <= 0xa4004c)
if(address >= 0x40 && address <= 0x4c)
//if(address == 0x4c)
wiimote_gen_key(&g_ExtKey, &g_RegExt[0x40]);
wiimote_gen_key(&g_ExtKey, &g_RegExt[0x40]);
}
// -------------
@ -363,71 +405,85 @@ void WmWriteData(u16 _channelID, wm_write_data* wd)
PanicAlert("WmWriteData: unimplemented parameters!");
}
// just added for home brew.... hmmmm
WmSendAck(_channelID, WM_WRITE_DATA);
/* Just added for home brew... Isn't it enough that we call this from
InterruptChannel()? Or is there a separate route here that don't pass though
InterruptChannel()? */
//WmSendAck(_channelID, WM_WRITE_DATA, _address);
LOGV(WII_IPC_WIIMOTE, 0, "==========================================================");
}
// ===================================================
/* Generate the right address for wm reports. */
/* Here we produce the actual 0x21 Input report that we send to the Wii. The message
is divided into 16 bytes pieces and sent piece by piece. There will be five formatting
bytes at the begging of all reports. A common format is 00 00 f0 00 20, the 00 00
means that no buttons are pressedn, the f means 16 bytes in the message, the 0
means no error, the 00 20 means that the message is at the 00 20 offest the the
registry that was read. */
// ----------------
int WriteWmReport(u8* dst, u8 channel) {
u32 Offset = 0;
hid_packet* pHidHeader = (hid_packet*)(dst + Offset);
Offset += sizeof(hid_packet);
pHidHeader->type = HID_TYPE_DATA;
pHidHeader->param = HID_PARAM_INPUT;
wm_report* pReport = (wm_report*)(dst + Offset);
Offset += sizeof(wm_report);
pReport->channel = channel;
return Offset;
}
// Custom call version
void WmRequestStatus_(u16 _channelID, int a)
void SendReadDataReply(u16 _channelID, void* _Base, u16 _Address, u8 _Size)
{
//PanicAlert("WmRequestStatus");
LOGV(WII_IPC_WIIMOTE, 0, "================================================");
LOGV(WII_IPC_WIIMOTE, 0, " Request Status");
LOGV(WII_IPC_WIIMOTE, 0, " Channel: %04x", _channelID);
//SendStatusReport();
u8 DataFrame[1024];
u32 Offset = WriteWmReport(DataFrame, WM_STATUS_REPORT);
wm_status_report* pStatus = (wm_status_report*)(DataFrame + Offset);
Offset += sizeof(wm_status_report);
memset(pStatus, 0, sizeof(wm_status_report)); // fill the status report with zeroes
// Status values
pStatus->leds = g_Leds;
pStatus->ir = 1;
pStatus->battery = 0x4F; //arbitrary number
if(a == 1)
LOGV(WII_IPC_WIIMOTE, 0, "=========================================");
int dataOffset = 0;
while (_Size > 0)
{
wprintf("pStatus->extension = 1\n");
pStatus->extension = 1;
}
else
{
wprintf("pStatus->extension = 0\n");
pStatus->extension = 0;
u8 DataFrame[1024];
u32 Offset = WriteWmReport(DataFrame, WM_READ_DATA_REPLY);
int copySize = _Size;
if (copySize > 16)
{
copySize = 16;
}
wm_read_data_reply* pReply = (wm_read_data_reply*)(DataFrame + Offset);
Offset += sizeof(wm_read_data_reply);
pReply->buttons = 0;
pReply->error = 0;
pReply->size = (copySize - 1) & 0xF;
pReply->address = Common::swap16(_Address + dataOffset);
// Write a pice
memcpy(pReply->data + dataOffset, _Base, copySize);
if(copySize < 16) // check if we have less than 16 bytes left to send
{
memset(pReply->data + copySize, 0, 16 - copySize);
}
dataOffset += copySize;
LOG(WII_IPC_WIIMOTE, " SendReadDataReply()");
LOG(WII_IPC_WIIMOTE, " Buttons: 0x%04x", pReply->buttons);
LOG(WII_IPC_WIIMOTE, " Error: 0x%x", pReply->error);
LOG(WII_IPC_WIIMOTE, " Size: 0x%x", pReply->size);
LOG(WII_IPC_WIIMOTE, " Address: 0x%04x", pReply->address);
/* Debugging
wprintf("SendReadDataReply Address: %08x\n", _Address);
for (int i = 0; i < Offset; i++)
{
wprintf("%02x ", DataFrame[i]);
if((i + 1) % 25 == 0) wprintf("\n");
}
wprintf("\n\n");*/
//---------
// Send a piece
g_WiimoteInitialize.pWiimoteInput(_channelID, DataFrame, Offset);
_Size -= copySize;
}
LOGV(WII_IPC_WIIMOTE, 0, " Extension: %x", pStatus->extension);
LOGV(WII_IPC_WIIMOTE, 0, " SendStatusReport()");
LOGV(WII_IPC_WIIMOTE, 0, " Flags: 0x%02x", pStatus->padding1[2]);
LOGV(WII_IPC_WIIMOTE, 0, " Battery: %d", pStatus->battery);
g_WiimoteInitialize.pWiimoteInput(_channelID, DataFrame, Offset);
LOGV(WII_IPC_WIIMOTE, 0, "=================================================");
if (_Size != 0)
{
PanicAlert("WiiMote-Plugin: SendReadDataReply() failed");
}
LOGV(WII_IPC_WIIMOTE, 0, "==========================================");
}
// ================
// ===================================================
@ -471,74 +527,4 @@ void WmRequestStatus(u16 _channelID, wm_request_status* rs)
LOGV(WII_IPC_WIIMOTE, 0, "=================================================");
}
// ===================================================
/* Here we produce the actual reply that we send to the Wii. The message is divided
into 16 bytes pieces and sent piece by piece. */
// ----------------
void SendReadDataReply(u16 _channelID, void* _Base, u16 _Address, u8 _Size)
{
LOGV(WII_IPC_WIIMOTE, 0, "=========================================");
int dataOffset = 0;
while (_Size > 0)
{
u8 DataFrame[1024];
u32 Offset = WriteWmReport(DataFrame, WM_READ_DATA_REPLY);
int copySize = _Size;
if (copySize > 16)
{
copySize = 16;
}
wm_read_data_reply* pReply = (wm_read_data_reply*)(DataFrame + Offset);
Offset += sizeof(wm_read_data_reply);
pReply->buttons = 0;
pReply->error = 0;
pReply->size = (copySize - 1) & 0xF;
pReply->address = Common::swap16(_Address + dataOffset);
// Write a pice
memcpy(pReply->data + dataOffset, _Base, copySize);
if(copySize < 16) // check if we have less than 16 bytes left to send
{
memset(pReply->data + copySize, 0, 16 - copySize);
}
dataOffset += copySize;
LOG(WII_IPC_WIIMOTE, " SendReadDataReply()");
LOG(WII_IPC_WIIMOTE, " Buttons: 0x%04x", pReply->buttons);
LOG(WII_IPC_WIIMOTE, " Error: 0x%x", pReply->error);
LOG(WII_IPC_WIIMOTE, " Size: 0x%x", pReply->size);
LOG(WII_IPC_WIIMOTE, " Address: 0x%04x", pReply->address);
// Debugging
/*
wprintf("SendReadDataReply\n");
for (int i = 0; i < sizeof(DataFrame); i++)
{
wprintf("%02x ", g_RegExt[i]);
if((i + 1) % 25 == 0) wprintf("\n");
}
wprintf("\n\n");
*/
//---------
// Send a piece
g_WiimoteInitialize.pWiimoteInput(_channelID, DataFrame, Offset);
_Size -= copySize;
}
if (_Size != 0)
{
PanicAlert("WiiMote-Plugin: SendReadDataReply() failed");
}
LOGV(WII_IPC_WIIMOTE, 0, "==========================================");
}
} // end of namespace

View File

@ -16,6 +16,27 @@
// http://code.google.com/p/dolphin-emu/
// ===================================================
/* HID reports access guide. */
// ----------------
/* 0x10 - 0x1a Output EmuMain.cpp: HidOutputReport()
0x10 - 0x14: General
0x15: Status report request from the Wii
0x16 and 0x17: Write and read memory or registers
0x19 and 0x1a: General
0x20 - 0x22 Input EmuMain.cpp: HidOutputReport() to the destination
0x15 leads to a 0x20 Input report
0x17 leads to a 0x21 Input report
0x10 - 0x1a leads to a 0x22 Input report
0x30 - 0x3f Input This file: Update() */
// ================
#include "pluginspecs_wiimote.h"
#include <vector>
@ -27,8 +48,6 @@
#include "Console.h" // for startConsoleWin, wprintf, GetConsoleHwnd
extern SWiimoteInitialize g_WiimoteInitialize;
//extern void __Log(int log, const char *format, ...);
//extern void __Log(int log, int v, const char *format, ...);
namespace WiiMoteEmu
{
@ -142,7 +161,7 @@ void InterruptChannel(u16 _channelID, const void* _pData, u32 _Size)
LOGV(WII_IPC_WIIMOTE, 0, "=============================================================");
const u8* data = (const u8*)_pData;
// dump raw data
// Debugging. Dump raw data.
{
LOG(WII_IPC_WIIMOTE, "Wiimote_Input");
std::string Temp;
@ -165,8 +184,16 @@ void InterruptChannel(u16 _channelID, const void* _pData, u32 _Size)
case HID_PARAM_OUTPUT:
{
wm_report* sr = (wm_report*)hidp->data;
WmSendAck(_channelID, sr->channel);
HidOutputReport(_channelID, sr);
/* This is the 0x22 answer to all Inputs. In most games it didn't matter
if it was written before or after HidOutputReport(), but Wii Sports
and Mario Galaxy would stop working if it was placed before
HidOutputReport(). */
wm_write_data *wd = (wm_write_data*)sr->data;
u32 address = convert24bit(wd->address);
WmSendAck(_channelID, sr->channel, address);
}
break;

View File

@ -48,8 +48,6 @@ extern u8 g_Eeprom[WIIMOTE_EEPROM_SIZE];
extern u8 g_RegSpeaker[WIIMOTE_REG_SPEAKER_SIZE];
extern u8 g_RegExt[WIIMOTE_REG_EXT_SIZE];
extern u8 g_RegExtTmp[WIIMOTE_REG_EXT_SIZE];
extern u8 g_RegExtBlnk[WIIMOTE_REG_EXT_SIZE];
extern u8 g_RegIr[WIIMOTE_REG_IR_SIZE];
extern u8 g_ReportingMode;
@ -57,6 +55,7 @@ extern u16 g_ReportingChannel;
extern wiimote_key g_ExtKey; // extension encryption key
static const u8 EepromData_0[] = {
0xA1, 0xAA, 0x8B, 0x99, 0xAE, 0x9E, 0x78, 0x30,
0xA7, 0x74, 0xD3, 0xA1, 0xAA, 0x8B, 0x99, 0xAE,
@ -74,7 +73,8 @@ static const u8 EepromData_16D0[] = {
/* Default calibration for the nunchuck. It should be written to 0x20 - 0x3f of the
extension register */
extension register. 0x80 is the neutral x and y accelerators and 0xb3 is the
neutral z accelerometer that is adjusted for gravity. */
static const u8 nunchuck_calibration[] =
{
0x80,0x80,0x80,0x00, 0xb3,0xb3,0xb3,0x00,
@ -89,7 +89,18 @@ static const u8 nunchuck_calibration[] =
static const u8 nunchuck_id[] =
{
0x00, 0x00, 0xa4, 0x20, 0x00, 0x00
//0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
/* The id for nothing inserted */
static const u8 nothing_id[] =
{
0x00, 0x00, 0x00, 0x00, 0x2e, 0x2e
};
/* The id for a partially inserted extension */
static const u8 partially_id[] =
{
0x00, 0x00, 0x00, 0x00, 0xff, 0xff
};
@ -110,7 +121,7 @@ void SendReportCoreAccelExt16(u16 _channelID);
void SendReportCoreAccelIr10Ext(u16 _channelID);
int WriteWmReport(u8* dst, u8 channel);
void WmSendAck(u16 _channelID, u8 _reportID);
void WmSendAck(u16 _channelID, u8 _reportID, u32 address);
void FillReportAcc(wm_accel& _acc);

View File

@ -30,8 +30,6 @@
#include "Config.h" // for g_Config
extern SWiimoteInitialize g_WiimoteInitialize;
//extern void __Log(int log, const char *format, ...);
//extern void __Log(int log, int v, const char *format, ...);
namespace WiiMoteEmu
@ -43,7 +41,7 @@ namespace WiiMoteEmu
/* Debugging. Read out the structs. */
/* Debugging. Read out the structs. */
void ReadExt()
{
for (int i = 0; i < WIIMOTE_REG_EXT_SIZE; i++)
@ -68,13 +66,6 @@ void ReadExtTmp()
}
/* The extension status can be a little difficult, this lets's us change the extension
status back and forth */
bool AllowReport = true;
int AllowCount = 0;
void FillReportInfo(wm_core& _core)
{
memset(&_core, 0x00, sizeof(wm_core));
@ -111,105 +102,28 @@ void FillReportInfo(wm_core& _core)
_core.right = GetAsyncKeyState(VK_RIGHT) ? 1 : 0;
_core.down = GetAsyncKeyState(VK_DOWN) ? 1 : 0;
}
/**/
// -----------------------
// Debugging. Send status report.
if(GetAsyncKeyState('I') && AllowReport)
{
//ClearScreen();
// Clear the register
//memcpy(g_RegExt, g_RegExtBlnk, sizeof(g_RegExt));
//g_RegExt[0xfc] = 0xa4;
//g_RegExt[0xfd] = 0x20;
// Clear the key part of the register
/**/
for(int i=0; i <= 16; i++)
{
g_RegExt[0x40 + i] = 0;
}
//wm_report sr;
//wm_request_status *sr;
//WmRequestStatus(g_ReportingChannel, sr);
/**/
WmRequestStatus_(g_ReportingChannel, 1);
wprintf("Sent status report\n");
AllowReport = false;
AllowCount = 0;
//void ReadExt();
}
/**/
if(GetAsyncKeyState('U') && AllowReport)
{
//ClearScreen();
//wm_report sr;
//wm_request_status *sr;
//WmRequestStatus(g_ReportingChannel, sr);
//memcpy(g_RegExt, g_RegExtBlnk, sizeof(g_RegExt));
//g_RegExt[0xfc] = 0xa4;
//g_RegExt[0xfd] = 0x20;
/**/
for(int i=0; i <= 16; i++)
{
g_RegExt[0x40 + i] = 0;
}
/* */
WmRequestStatus_(g_ReportingChannel, 0);
wprintf("Sent status report\n");
AllowReport = false;
AllowCount = 0;
//void ReadExt();
}
/**/
if(AllowCount > 10)
{
AllowReport = true;
AllowCount = 0;
}
AllowCount++;
// ----------
#else
// TODO: fill in
#endif
}
// -----------------------------
// Global declarations for FillReportAcc. The accelerometer x, y and z values range from
// 0x00 to 0xff with [y = 0x80, x = 0x80, z ~ 0xa0] being neutral and 0x00 being (-)
// and 0xff being (+). Or does it not? It's important that all values are not 0x80,
// the the mouse pointer can disappear from the screen permanently, until z is adjusted
// back.
/* Global declarations for FillReportAcc. The accelerometer x, y and z values range from
0x00 to 0xff with the default netural values being [y = 0x84, x = 0x84, z = 0x9f]
according to a source. The extremes are 0x00 for (-) and 0xff for (+). It's important
that all values are not 0x80, the the mouse pointer can disappear from the screen
permanently then, until z is adjusted back. */
// ----------
// the variables are global so they can be changed during debugging
//int A = 0, B = 128, C = 64; // for debugging
//int a = 1, b = 1, c = 2, d = -2; // for debugging
//int consoleDisplay = 0;
int X = 0x80, Y = 0x80, Z = 160; // neutral values
u8 x = 0x0, y = 0x0, z = 0x00;
int X = 0x84, Y = 0x84, Z = 0x9f; // neutral values
u8 x = X, y = Y, z = Z;
int shake = -1, yhistsize = 15; // for the shake function
std::vector<u8> yhist(15); // for the tilt function
void FillReportAcc(wm_accel& _acc)
{
#ifdef _WIN32
@ -240,13 +154,11 @@ void FillReportAcc(wm_accel& _acc)
}
// Single shake of Wiimote while holding it sideways (Wario Land pound ground)
/*
/* Single shake of Wiimote while holding it sideways (Wario Land pound ground)
if(GetAsyncKeyState('S'))
z = 0;
else
z = Z;
*/
z = Z;*/
if(GetAsyncKeyState('S'))
{
@ -266,6 +178,10 @@ void FillReportAcc(wm_accel& _acc)
y = Y;
shake = -1;
}
else // the default Y and Z if nothing is pressed
{
z = Z;
}
// ----------
@ -288,7 +204,7 @@ void FillReportAcc(wm_accel& _acc)
if(!ypressed) // y was not pressed a single time
{
y = Y;
y = Y; // this is the default value that will occur most of the time
//a = 0; // for debugging
//b = 0;
}
@ -319,7 +235,6 @@ void FillReportAcc(wm_accel& _acc)
consoleDisplay = 0;
}
if(GetAsyncKeyState('5'))
A-=1;
else if(GetAsyncKeyState('6'))
@ -332,18 +247,7 @@ void FillReportAcc(wm_accel& _acc)
C-=1;
else if(GetAsyncKeyState('0'))
C+=1;
else if(GetAsyncKeyState(VK_INSERT))
a-=1;
else if(GetAsyncKeyState(VK_DELETE))
a+=1;
else if(GetAsyncKeyState(VK_HOME))
b-=1;
else if(GetAsyncKeyState(VK_END))
b+=1;
else if(GetAsyncKeyState(VK_SHIFT))
c-=1;
else if(GetAsyncKeyState(VK_CONTROL))
c+=1;
else if(GetAsyncKeyState(VK_NUMPAD3))
d-=1;
else if(GetAsyncKeyState(VK_NUMPAD6))
@ -353,7 +257,21 @@ void FillReportAcc(wm_accel& _acc)
else if(GetAsyncKeyState(VK_SUBTRACT))
yhistsize+=1;
/*if(GetAsyncKeyState(VK_INSERT))
AX-=1;
else if(GetAsyncKeyState(VK_DELETE))
AX+=1;
else if(GetAsyncKeyState(VK_HOME))
AY-=1;
else if(GetAsyncKeyState(VK_END))
AY+=1;
else if(GetAsyncKeyState(VK_SHIFT))
AZ-=1;
else if(GetAsyncKeyState(VK_CONTROL))
AZ+=1;*/
/*
if(GetAsyncKeyState(VK_NUMPAD1))
X+=1;
else if(GetAsyncKeyState(VK_NUMPAD2))
@ -367,49 +285,24 @@ void FillReportAcc(wm_accel& _acc)
else if(GetAsyncKeyState(VK_NUMPAD8))
Z-=1;
/*
if(GetAsyncKeyState('S'))
{
z = Z + C;
}
else
{
z = Z;
}
if(GetAsyncKeyState('D'))
{
y = Y + B;
}
else
{
y = Y;
}
if(GetAsyncKeyState('F'))
{
z = Z + C;
y = Y + B;
}
else if(!GetAsyncKeyState('S') && !GetAsyncKeyState('D'))
{
z = Z;
y = Y;
}
if(consoleDisplay == 0)
wprintf("x: %03i | y: %03i | z: %03i | A:%i B:%i C:%i a:%i b:%i c:%i d:%i X:%i Y:%i Z:%i\n", _acc.x, _acc.y, _acc.z,
//if(consoleDisplay == 0)
wprintf("x: %03i | y: %03i | z: %03i | A:%i B:%i C:%i a:%i b:%i c:%i d:%i X:%i Y:%i Z:%i\n",
_acc.x, _acc.y, _acc.z,
A, B, C,
a, b, c, d,
X, Y, Z);
*/
X, Y, Z
);
wprintf("x: %03i | y: %03i | z: %03i | X:%i Y:%i Z:%i | AX:%i AY:%i AZ:%i \n",
_acc.x, _acc.y, _acc.z,
X, Y, Z,
AX, AY, AZ
);*/
#else
// TODO port to linux
#endif
}
//bool toggleWideScreen = false, toggleCursor = true;
void FillReportIR(wm_ir_extended& _ir0, wm_ir_extended& _ir1)
{
@ -417,7 +310,6 @@ void FillReportIR(wm_ir_extended& _ir0, wm_ir_extended& _ir1)
/* DESCRIPTION: The calibration is controlled by these values, their absolute value and
the relative distance between between them control the calibration. WideScreen mode
has its own settings. */
/**/
int Top, Left, Right, Bottom, SensorBarRadius;
if(g_Config.bWideScreen)
{
@ -429,8 +321,8 @@ void FillReportIR(wm_ir_extended& _ir0, wm_ir_extended& _ir1)
Top = TOP; Left = LEFT; Right = RIGHT;
Bottom = BOTTOM; SensorBarRadius = SENSOR_BAR_RADIUS;
}
// Fill with 0xff if empty
memset(&_ir0, 0xFF, sizeof(wm_ir_extended));
memset(&_ir1, 0xFF, sizeof(wm_ir_extended));
@ -451,7 +343,7 @@ void FillReportIR(wm_ir_extended& _ir0, wm_ir_extended& _ir1)
_ir0.yHi = y0 >> 8;
x1 = 1023 - x1;
_ir1.x = x1;
_ir1.x = x1 & 0xFF;
_ir1.y = y1 & 0xFF;
_ir1.size = 10;
_ir1.xHi = x1 >> 8;
@ -488,13 +380,20 @@ void FillReportIR(wm_ir_extended& _ir0, wm_ir_extended& _ir1)
wprintf("x0:%03i x1:%03i y0:%03i y1:%03i irx0:%03i y0:%03i x1:%03i y1:%03i | T:%i L:%i R:%i B:%i S:%i\n",
x0, x1, y0, y1, _ir0.x, _ir0.y, _ir1.x, _ir1.y, Top, Left, Right, Bottom, SensorBarRadius
);
*/
wprintf("\n");
wprintf("ir0.x:%02x xHi:%02x ir1.x:%02x xHi:%02x | ir0.y:%02x yHi:%02x ir1.y:%02x yHi:%02x | 1.s:%02x 2:%02x\n",
_ir0.x, _ir0.xHi, _ir1.x, _ir1.xHi,
_ir0.y, _ir0.yHi, _ir1.y, _ir1.yHi,
_ir0.size, _ir1.size
);*/
}
void FillReportIRBasic(wm_ir_basic& _ir0, wm_ir_basic& _ir1)
{
/* See description above */
int Top, Left, Right, Bottom, SensorBarRadius;
if(g_Config.bWideScreen)
{
Top = wTOP; Left = wLEFT; Right = wRIGHT;
@ -506,8 +405,9 @@ void FillReportIRBasic(wm_ir_basic& _ir0, wm_ir_basic& _ir1)
Bottom = BOTTOM; SensorBarRadius = SENSOR_BAR_RADIUS;
}
memset(&_ir0, 0xFF, sizeof(wm_ir_basic));
memset(&_ir1, 0xFF, sizeof(wm_ir_basic));
// Fill with 0xff if empty
memset(&_ir0, 0xff, sizeof(wm_ir_basic));
memset(&_ir1, 0xff, sizeof(wm_ir_basic));
float MouseX, MouseY;
GetMousePos(MouseX, MouseY);
@ -518,17 +418,23 @@ void FillReportIRBasic(wm_ir_basic& _ir0, wm_ir_basic& _ir1)
int x1 = Left + (MouseX * (Right - Left)) - SensorBarRadius;
int x2 = Left + (MouseX * (Right - Left)) + SensorBarRadius;
/* As with the extented report we settle with emulating two out of four
possible objects */
x1 = 1023 - x1;
_ir0.x1 = x1 & 0xFF;
_ir0.y1 = y1 & 0xFF;
_ir0.x1Hi = (x1 >> 8) & 0x3;
_ir0.y1Hi = (y1 >> 8) & 0x3;
_ir0.x1 = x1 & 0xff;
_ir0.y1 = y1 & 0xff;
_ir0.x1Hi = (x1 >> 8); // we are dealing with 2 bit values here
_ir0.y1Hi = (y1 >> 8);
x2 = 1023 - x2;
_ir1.x2 = x2 & 0xFF;
_ir1.y2 = y2 & 0xFF;
_ir1.x2Hi = (x2 >> 8) & 0x3;
_ir1.y2Hi = (y2 >> 8) & 0x3;
_ir0.x2 = x2 & 0xff;
_ir0.y2 = y2 & 0xff;
_ir0.x2Hi = (x2 >> 8);
_ir0.y2Hi = (y2 >> 8);
// I don't understand't the & 0x03, should we do that?
//_ir1.x1Hi = (x1 >> 8) & 0x3;
//_ir1.y1Hi = (y1 >> 8) & 0x3;
// ----------------------------
// Debugging for calibration
@ -557,46 +463,50 @@ void FillReportIRBasic(wm_ir_basic& _ir0, wm_ir_basic& _ir1)
//ClearScreen();
//if(consoleDisplay == 1)
wprintf("x1:%03i x2:%03i y1:%03i y2:%03i irx1:%03i y1:%03i x2:%03i y2:%03i | T:%i L:%i R:%i B:%i S:%i\n",
wprintf("x1:%03i x2:%03i y1:%03i y2:%03i irx1:%02x y1:%02x x2:%02x y2:%02x | T:%i L:%i R:%i B:%i S:%i\n",
x1, x2, y1, y2, _ir0.x1, _ir0.y1, _ir1.x2, _ir1.y2, Top, Left, Right, Bottom, SensorBarRadius
);
wprintf("\n");
wprintf("ir0.x1:%02x x1h:%02x x2:%02x x2h:%02x | ir0.y1:%02x y1h:%02x y2:%02x y2h:%02x | ir1.x1:%02x x1h:%02x x2:%02x x2h:%02x | ir1.y1:%02x y1h:%02x y2:%02x y2h:%02x\n",
_ir0.x1, _ir0.x1Hi, _ir0.x2, _ir0.x2Hi,
_ir0.y1, _ir0.y1Hi, _ir0.y2, _ir0.y2Hi,
_ir1.x1, _ir1.x1Hi, _ir1.x2, _ir1.x2Hi,
_ir1.y1, _ir1.y1Hi, _ir1.y2, _ir1.y2Hi
);*/
}
// ===================================================
/* Generate the 6 byte extension report, encrypted. */
/* Generate the 6 byte extension report, encrypted. The bytes are JX JY AX AY AZ BT. */
// ----------------
void FillReportExtension(wm_extension& _ext)
{
// JX JY AX AY AZ BT
// Make temporary values
/* These are the default neutral values for the nunchuck accelerometer according
to a source. */
_ext.ax = 0x80;
_ext.ay = 0x80;
_ext.az = 0xb3;
_ext.jx = 0x80; // these are the default values unless we don't use them
_ext.jx = 0x80; // these are the default values unless we use them
_ext.jy = 0x80;
_ext.bt = 0x03; // 0x03 means no button pressed, the button is zero active
#ifdef _WIN32
if(GetAsyncKeyState(VK_NUMPAD4))
_ext.jx = 0x20;
if(GetAsyncKeyState(VK_NUMPAD8))
_ext.jy = 0x20;
_ext.jy = 0xe0;
if(GetAsyncKeyState(VK_NUMPAD6))
_ext.jx = 0xe0;
if(GetAsyncKeyState(VK_NUMPAD5))
_ext.jy = 0xe0;
_ext.jy = 0x20;
@ -612,8 +522,8 @@ void FillReportExtension(wm_extension& _ext)
// TODO linux port
#endif
// Clear g_RegExtTmp by copying g_RegExtBlnk to g_RegExtTmp
memcpy(g_RegExtTmp, g_RegExtBlnk, sizeof(g_RegExt));
// Clear g_RegExtTmp by copying zeroes to it
memset(g_RegExtTmp, 0, sizeof(g_RegExtTmp));
// Write the nunchuck inputs to it
g_RegExtTmp[0x08] = _ext.jx;
@ -636,8 +546,4 @@ void FillReportExtension(wm_extension& _ext)
}
} // end of namespace

View File

@ -164,7 +164,7 @@ extern "C" void Wiimote_InterruptChannel(u16 _channelID, const void* _pData, u32
LOGV(WII_IPC_WIIMOTE, 0, "=============================================================");
const u8* data = (const u8*)_pData;
// dump raw data
// Debugging. Dump raw data.
{
LOG(WII_IPC_WIIMOTE, "Wiimote_Input");
LOG(WII_IPC_WIIMOTE, " Channel ID: %04x", _channelID);
@ -222,6 +222,9 @@ extern "C" unsigned int Wiimote_GetAttachedControllers()
}
// ===================================================
/* Logging functions. */
// ----------------
void __Log(int log, const char *_fmt, ...)
{
char Msg[512];
@ -246,3 +249,4 @@ void __Logv(int log, int v, const char *_fmt, ...)
g_WiimoteInitialize.pLog(Msg, v);
}
// ================

View File

@ -167,6 +167,14 @@ struct wm_ir_basic
u8 y2;
};
struct wm_ir_extended
{
u8 x;
u8 y;
u8 size : 4;
u8 xHi : 2;
u8 yHi : 2;
};
struct wm_extension
{
@ -178,16 +186,6 @@ struct wm_extension
u8 bt; // buttons
};
struct wm_ir_extended
{
u8 x;
u8 y;
u8 size : 4;
u8 xHi : 2;
u8 yHi : 2;
};
#define WM_REPORT_CORE 0x30
struct wm_report_core {
wm_core c;