mirror of
https://github.com/gligli/nulldc-360.git
synced 2025-04-02 11:11:56 -04:00
205 lines
5.3 KiB
C++
205 lines
5.3 KiB
C++
#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
|