nulldc-360/plugins/XMaple/Maxi.cpp
2011-10-15 12:33:03 +02:00

205 lines
5.3 KiB
C++
Raw Permalink Blame History

#include "FT8.h"
#include "Maxi.h"
#include "XMaple.h" // for debug log crapro
namespace EmulatedDevices
{
Maxi::Maxi(maple_subdevice_instance* instance)
: FT8(instance)
{
m_deviceID = ID_PURUPURUPACK;
m_FuncDef[0] = 0x00000101;
m_strName = "Puru Puru Pack";
m_mAstandby = 0x00C8;
m_mAmax = 0x0640;
m_strNameEx = "Version 1.000,1998/11/10,315-6211-AH ,Vibration Motor:1,Fm:4 <20>E30Hz,Pow:7 ";
// init with maxi srcSettings
m_status.AST = 0x13; // AST of 5 secs
m_status.srcSettings.VN = 1;
m_status.srcSettings.VP = 0;
m_status.srcSettings.VD = 0;
m_status.srcSettings.PF = 1;
m_status.srcSettings.CV = 1;
m_status.srcSettings.PD = 1;
m_status.srcSettings.OWF= 0;
m_status.srcSettings.VA = 0;
m_status.srcSettings.Fm0= 0x07;
m_status.srcSettings.Fm1= 0x3B;
m_status.currentXPad = m_xpad;
}
void Maxi::StartVibThread()
{
DEBUG_LOG(" VIBRATION THREAD STARTING...\n");
//gli CreateThread(0, 0, (LPTHREAD_START_ROUTINE)XInput::VibrationThread, &m_status, 0, NULL);
InitializeCriticalSection(&m_status.section);
}
void Maxi::StopVibThread()
{
// Kill thread or whatever
XInput::StopRumble(m_xpad);
// It crashes when using Xmaple as main device too and closing the GUI.
// Doesn't crash when using PuruPuru as main device, nor when closing through console.
// TODO: Find out why. =S
//gli CloseHandle(m_thread);
//gli TerminateThread(m_thread, 0);
DEBUG_LOG(" VIBRATION THREAD STOPPED\n");
}
u32 Maxi::DMA(u32 Command,
u32* buffer_in, u32 buffer_in_len,
u32* buffer_out, u32& buffer_out_len)
{
// Update the xpad the thread uses...
EnterCriticalSection(&m_status.section);
m_status.currentXPad = m_xpad;
LeaveCriticalSection(&m_status.section);
u8* buffer_out_b = (u8*)buffer_out;
switch (Command)
{
case GetStatus:
//functionality info
w32(m_FuncType);
w32(m_FuncDef[0]);
w32(m_FuncDef[1]);
w32(m_FuncDef[2]);
w8(m_Region);
w8(m_Direction);
wString(m_strName, 30);
wString(m_License, 60);
w16(m_mAstandby);
w16(m_mAmax);
DEBUG_LOG("GetStatus\n");
return DeviceInfo;
case GetStatusAll:
w32(m_FuncType);
w32(m_FuncDef[0]);
w32(m_FuncDef[1]);
w32(m_FuncDef[2]);
w8(m_Region);
w8(m_Direction);
wString(m_strName, 30);
wString(m_License, 60);
w16(m_mAstandby);
w16(m_mAmax);
wString(m_strNameEx, 40);
DEBUG_LOG("GetStatusAll\n");
return DeviceInfoEx;
case GetCondition:
// This command should return ALL vibration sources' settings. we only have one at the moment...
w32(m_FuncType);
w32(m_status.srcSettings.U32);
DEBUG_LOG("GetCondition\n");
//w32(purupuru_cond.srcSettings[VN].U32);
return DataTransfer;
case GetMediaInfo:
{
if (!m_status.srcSettings.VN) // there are no vibration sources?!?!
return TransmitAgain;
w32(m_FuncType);
w32(m_status.srcSettings.U32);
u8 source = (*(++buffer_in) & 0x000000FF);
DEBUG_LOG("GetMediaInfo for source 0x%02x\n", source);
}
return DataTransfer;
case BlockRead:
if (*(++buffer_in) == 0) // It's not looking for waveform data
{
// Read back the AutoStop settings
w32(m_FuncType);
w32(0); // VN(1), Phase(1), Block No.(2)
w16(0x0200); // ASR for VN 1
w8(m_status.AST);
}
else
{
printf("BlockRead for waveform!\n");
printf("REPORT THIS\n");
return CommandUnknown;
}
return DataTransfer;
case BlockWrite:
{
// GAH this can also be used to set auto stop time so we have to support it
if (*(++buffer_in) == 0) // It's not trying to send waveform data
{
int numAST = (buffer_in_len-6)/4; // Doesn't include VN(1), Phase(1), Block Number(2), or ASR(2)
// example ASR and AST (as the game sends): 0x000c0200
buffer_in++;
u16 ASR = (u16)*(buffer_in) & 0x0000FFFF; // don't swap ASR because I am lazy
if (numAST == 1 && ASR == 0x0200) // yeah, we'll handle it
{
EnterCriticalSection(&m_status.section);
m_status.AST = (*(buffer_in) & 0x00FF0000) >> 16;
LeaveCriticalSection(&m_status.section);
DEBUG_LOG("BlockWrite set AutoStop: %f seconds\n", m_status.AST * .25);
}
else
{
printf("BlockWrite set numAST: %i ASR: 0x%04x\n", numAST, ASR);
printf("REPORT THIS\n");
return TransmitAgain;
}
}
else
{
u32 buffer = *(buffer_in);
u32 buffer2 = *(++buffer_in);
printf("BlockWrite set waveform: 0x%08x 0x%08x...\n", buffer, buffer2);
printf("REPORT THIS\n");
return CommandUnknown;
}
}
return DeviceReply;
case SetCondition:
{
int numSources = (buffer_in_len-4)/4;
// numsources to be set greater than number of sources which can be concurrently selected?
if (numSources > (u8)(m_FuncDef[0]>>8))
return TransmitAgain;
EnterCriticalSection(&m_status.section);
m_status.config.U32 = *(++buffer_in);
LeaveCriticalSection(&m_status.section);
// convergent and divergent can't be set at the same time
if (m_status.config.INH && m_status.config.EXH)
return TransmitAgain;
DEBUG_LOG(" VN: %01x CNT: %01x INH: %01x Ppow: %01x EXH: %01x Mpow: %01x Freq: %02x Inc: %02x\n",
m_status.config.VN,
m_status.config.CNT,
m_status.config.INH,
m_status.config.Ppow,
m_status.config.EXH,
m_status.config.Mpow,
m_status.config.FREQ,
m_status.config.INC);
}
return DeviceReply;
default:
printf("UNKNOWN MAPLE COMMAND %d (sent to maxi)\n", Command);
return CommandUnknown;
}
}
} //namespace