convert DSi I2C and camera

This commit is contained in:
Arisotura 2023-11-04 19:42:36 +01:00
parent 7837c169a1
commit 54ebf1b1b2
12 changed files with 400 additions and 367 deletions

View File

@ -79,6 +79,8 @@ std::unique_ptr<DSi_NAND::NANDImage> NANDImage;
DSi_SDHost* SDMMC;
DSi_SDHost* SDIO;
DSi_I2CHost* I2C;
DSi_CamModule* CamModule;
DSi_AES* AES;
// FIXME: these currently have no effect (and aren't stored in a savestate)
@ -102,8 +104,6 @@ bool Init()
NWRAM_C = new u8[NWRAMSize];
#endif
if (!DSi_I2C::Init()) return false;
if (!DSi_CamModule::Init()) return false;
if (!DSi_DSP::Init()) return false;
NDMAs[0] = new DSi_NDMA(0, 0);
@ -118,6 +118,8 @@ bool Init()
SDMMC = new DSi_SDHost(0);
SDIO = new DSi_SDHost(1);
I2C = new DSi_I2CHost();
CamModule = new DSi_CamModule();
AES = new DSi_AES();
return true;
@ -135,8 +137,6 @@ void DeInit()
NWRAM_C = nullptr;
#endif
DSi_I2C::DeInit();
DSi_CamModule::DeInit();
DSi_DSP::DeInit();
for (int i = 0; i < 8; i++)
@ -148,6 +148,8 @@ void DeInit()
delete SDMMC; SDMMC = nullptr;
delete SDIO; SDIO = nullptr;
delete I2C; I2C = nullptr;
delete CamModule; CamModule = nullptr;
delete AES; AES = nullptr;
NANDImage = nullptr;
@ -166,8 +168,8 @@ void Reset()
NDMACnt[0] = 0; NDMACnt[1] = 0;
for (int i = 0; i < 8; i++) NDMAs[i]->Reset();
DSi_I2C::Reset();
DSi_CamModule::Reset();
I2C->Reset();
CamModule->Reset();
DSi_DSP::Reset();
SDMMC->CloseHandles();
@ -210,7 +212,7 @@ void Reset()
void Stop()
{
DSi_CamModule::Stop();
CamModule->Stop();
}
void DoSavestate(Savestate* file)
@ -285,9 +287,9 @@ void DoSavestate(Savestate* file)
NDMAs[i]->DoSavestate(file);
AES->DoSavestate(file);
DSi_CamModule::DoSavestate(file);
CamModule->DoSavestate(file);
DSi_DSP::DoSavestate(file);
DSi_I2C::DoSavestate(file);
I2C->DoSavestate(file);
SDMMC->DoSavestate(file);
SDIO->DoSavestate(file);
}
@ -581,7 +583,7 @@ void SetupDirectBoot()
ARM9Write32(0x02FFFC00, cartid);
ARM9Write16(0x02FFFC40, 0x0001); // boot indicator
ARM9Write8(0x02FFFDFA, DSi_BPTWL::GetBootFlag() | 0x80);
ARM9Write8(0x02FFFDFA, I2C->GetBPTWL()->GetBootFlag() | 0x80);
ARM9Write8(0x02FFFDFB, 0x01);
}
@ -2302,7 +2304,7 @@ u8 ARM9IORead8(u32 addr)
if ((addr & 0xFFFFFF00) == 0x04004200)
{
if (!(SCFG_EXT[0] & (1<<17))) return 0;
return DSi_CamModule::Read8(addr);
return CamModule->Read8(addr);
}
if ((addr & 0xFFFFFF00) == 0x04004300)
@ -2337,7 +2339,7 @@ u16 ARM9IORead16(u32 addr)
if ((addr & 0xFFFFFF00) == 0x04004200)
{
if (!(SCFG_EXT[0] & (1<<17))) return 0;
return DSi_CamModule::Read16(addr);
return CamModule->Read16(addr);
}
if ((addr & 0xFFFFFF00) == 0x04004300)
@ -2402,7 +2404,7 @@ u32 ARM9IORead32(u32 addr)
if ((addr & 0xFFFFFF00) == 0x04004200)
{
if (!(SCFG_EXT[0] & (1<<17))) return 0;
return DSi_CamModule::Read32(addr);
return CamModule->Read32(addr);
}
if ((addr & 0xFFFFFF00) == 0x04004300)
@ -2472,7 +2474,7 @@ void ARM9IOWrite8(u32 addr, u8 val)
if ((addr & 0xFFFFFF00) == 0x04004200)
{
if (!(SCFG_EXT[0] & (1<<17))) return;
return DSi_CamModule::Write8(addr, val);
return CamModule->Write8(addr, val);
}
if ((addr & 0xFFFFFF00) == 0x04004300)
@ -2532,7 +2534,7 @@ void ARM9IOWrite16(u32 addr, u16 val)
if ((addr & 0xFFFFFF00) == 0x04004200)
{
if (!(SCFG_EXT[0] & (1<<17))) return;
return DSi_CamModule::Write16(addr, val);
return CamModule->Write16(addr, val);
}
if ((addr & 0xFFFFFF00) == 0x04004300)
@ -2682,7 +2684,7 @@ void ARM9IOWrite32(u32 addr, u32 val)
if ((addr & 0xFFFFFF00) == 0x04004200)
{
if (!(SCFG_EXT[0] & (1<<17))) return;
return DSi_CamModule::Write32(addr, val);
return CamModule->Write32(addr, val);
}
if ((addr & 0xFFFFFF00) == 0x04004300)
@ -2715,8 +2717,8 @@ u8 ARM7IORead8(u32 addr)
CASE_READ8_32BIT(0x0400405C, MBK[1][7])
CASE_READ8_32BIT(0x04004060, MBK[1][8])
case 0x04004500: return DSi_I2C::ReadData();
case 0x04004501: return DSi_I2C::Cnt;
case 0x04004500: return I2C->ReadData();
case 0x04004501: return I2C->ReadCnt();
case 0x04004D00: if (SCFG_BIOS & (1<<10)) return 0; return NANDImage->GetConsoleID() & 0xFF;
case 0x04004D01: if (SCFG_BIOS & (1<<10)) return 0; return (NANDImage->GetConsoleID() >> 8) & 0xFF;
@ -2899,8 +2901,8 @@ void ARM7IOWrite8(u32 addr, u8 val)
return;
}
case 0x04004500: DSi_I2C::WriteData(val); return;
case 0x04004501: DSi_I2C::WriteCnt(val); return;
case 0x04004500: I2C->WriteData(val); return;
case 0x04004501: I2C->WriteCnt(val); return;
case 0x4004700:
DSi_DSP::WriteSNDExCnt((u16)val | (DSi_DSP::SNDExCnt & 0xFF00));

View File

@ -22,6 +22,8 @@
#include "NDS.h"
#include "DSi_SD.h"
class DSi_I2CHost;
class DSi_CamModule;
class DSi_AES;
namespace DSi_NAND
@ -58,6 +60,8 @@ extern u32 NWRAMStart[2][3];
extern u32 NWRAMEnd[2][3];
extern u32 NWRAMMask[2][3];
extern DSi_I2CHost* I2C;
extern DSi_CamModule* CamModule;
extern DSi_AES* AES;
bool Init();

View File

@ -25,48 +25,27 @@
using Platform::Log;
using Platform::LogLevel;
namespace DSi_CamModule
{
Camera* Camera0; // 78 / facing outside
Camera* Camera1; // 7A / selfie cam
u16 ModuleCnt;
u16 Cnt;
u32 CropStart, CropEnd;
// pixel data buffer holds a maximum of 512 words, regardless of how long scanlines are
u32 DataBuffer[512];
u32 BufferReadPos, BufferWritePos;
u32 BufferNumLines;
Camera* CurCamera;
// note on camera data/etc intervals
// on hardware those are likely affected by several factors
// namely, how long cameras take to process frames
// camera IRQ is fired at roughly 15FPS with default config
const u32 kIRQInterval = 1120000; // ~30 FPS
const u32 kTransferStart = 60000;
const u32 DSi_CamModule::kIRQInterval = 1120000; // ~30 FPS
const u32 DSi_CamModule::kTransferStart = 60000;
bool Init()
DSi_CamModule::DSi_CamModule()
{
NDS::RegisterEventFunc(NDS::Event_DSi_CamIRQ, 0, IRQ);
NDS::RegisterEventFunc(NDS::Event_DSi_CamTransfer, 0, TransferScanline);
NDS::RegisterEventFunc(NDS::Event_DSi_CamIRQ, 0, MemberEventFunc(DSi_CamModule, IRQ));
NDS::RegisterEventFunc(NDS::Event_DSi_CamTransfer, 0, MemberEventFunc(DSi_CamModule, TransferScanline));
Camera0 = new Camera(0);
Camera1 = new Camera(1);
return true;
Camera0 = DSi::I2C->GetOuterCamera();
Camera1 = DSi::I2C->GetInnerCamera();
}
void DeInit()
DSi_CamModule::~DSi_CamModule()
{
delete Camera0;
delete Camera1;
Camera0 = nullptr;
Camera1 = nullptr;
@ -74,11 +53,8 @@ void DeInit()
NDS::UnregisterEventFunc(NDS::Event_DSi_CamTransfer, 0);
}
void Reset()
void DSi_CamModule::Reset()
{
Camera0->Reset();
Camera1->Reset();
ModuleCnt = 0; // CHECKME
Cnt = 0;
@ -94,13 +70,13 @@ void Reset()
NDS::ScheduleEvent(NDS::Event_DSi_CamIRQ, false, kIRQInterval, 0, 0);
}
void Stop()
void DSi_CamModule::Stop()
{
Camera0->Stop();
Camera1->Stop();
}
void DoSavestate(Savestate* file)
void DSi_CamModule::DoSavestate(Savestate* file)
{
file->Section("CAMi");
@ -110,15 +86,12 @@ void DoSavestate(Savestate* file)
/*file->VarArray(FrameBuffer, sizeof(FrameBuffer));
file->Var32(&TransferPos);
file->Var32(&FrameLength);*/
Camera0->DoSavestate(file);
Camera1->DoSavestate(file);
}
void IRQ(u32 param)
void DSi_CamModule::IRQ(u32 param)
{
Camera* activecam = nullptr;
DSi_Camera* activecam = nullptr;
// TODO: cameras don't have any priority!
// activating both together will jumble the image data together
@ -145,7 +118,7 @@ void IRQ(u32 param)
NDS::ScheduleEvent(NDS::Event_DSi_CamIRQ, true, kIRQInterval, 0, 0);
}
void TransferScanline(u32 line)
void DSi_CamModule::TransferScanline(u32 line)
{
u32* dstbuf = &DataBuffer[BufferWritePos];
int maxlen = 512 - BufferWritePos;
@ -252,7 +225,7 @@ void TransferScanline(u32 line)
}
u8 Read8(u32 addr)
u8 DSi_CamModule::Read8(u32 addr)
{
//
@ -260,7 +233,7 @@ u8 Read8(u32 addr)
return 0;
}
u16 Read16(u32 addr)
u16 DSi_CamModule::Read16(u32 addr)
{
switch (addr)
{
@ -272,7 +245,7 @@ u16 Read16(u32 addr)
return 0;
}
u32 Read32(u32 addr)
u32 DSi_CamModule::Read32(u32 addr)
{
switch (addr)
{
@ -298,14 +271,14 @@ u32 Read32(u32 addr)
return 0;
}
void Write8(u32 addr, u8 val)
void DSi_CamModule::Write8(u32 addr, u8 val)
{
//
Log(LogLevel::Debug, "unknown DSi cam write8 %08X %02X\n", addr, val);
}
void Write16(u32 addr, u16 val)
void DSi_CamModule::Write16(u32 addr, u16 val)
{
switch (addr)
{
@ -384,7 +357,7 @@ void Write16(u32 addr, u16 val)
Log(LogLevel::Debug, "unknown DSi cam write16 %08X %04X\n", addr, val);
}
void Write32(u32 addr, u32 val)
void DSi_CamModule::Write32(u32 addr, u32 val)
{
switch (addr)
{
@ -403,16 +376,15 @@ void Write32(u32 addr, u32 val)
Camera::Camera(u32 num)
{
Num = num;
}
Camera::~Camera()
DSi_Camera::DSi_Camera(DSi_I2CHost* host, u32 num) : DSi_I2CDevice(host), Num(num)
{
}
void Camera::DoSavestate(Savestate* file)
DSi_Camera::~DSi_Camera()
{
}
void DSi_Camera::DoSavestate(Savestate* file)
{
char magic[5] = "CAMx";
magic[3] = '0' + Num;
@ -433,7 +405,7 @@ void Camera::DoSavestate(Savestate* file)
file->VarArray(MCURegs, 0x8000);
}
void Camera::Reset()
void DSi_Camera::Reset()
{
Platform::Camera_Stop(Num);
@ -458,12 +430,12 @@ void Camera::Reset()
memset(FrameBuffer, 0, (640*480/2)*sizeof(u32));
}
void Camera::Stop()
void DSi_Camera::Stop()
{
Platform::Camera_Stop(Num);
}
bool Camera::IsActivated()
bool DSi_Camera::IsActivated()
{
if (StandbyCnt & (1<<14)) return false; // standby
if (!(MiscCnt & (1<<9))) return false; // data transfer not enabled
@ -472,7 +444,7 @@ bool Camera::IsActivated()
}
void Camera::StartTransfer()
void DSi_Camera::StartTransfer()
{
TransferY = 0;
@ -502,12 +474,12 @@ void Camera::StartTransfer()
Platform::Camera_CaptureFrame(Num, FrameBuffer, 640, 480, true);
}
bool Camera::TransferDone()
bool DSi_Camera::TransferDone()
{
return TransferY >= FrameHeight;
}
int Camera::TransferScanline(u32* buffer, int maxlen)
int DSi_Camera::TransferScanline(u32* buffer, int maxlen)
{
if (TransferY >= FrameHeight)
return 0;
@ -560,12 +532,12 @@ int Camera::TransferScanline(u32* buffer, int maxlen)
}
void Camera::I2C_Start()
void DSi_Camera::Acquire()
{
DataPos = 0;
}
u8 Camera::I2C_Read(bool last)
u8 DSi_Camera::Read(bool last)
{
u8 ret;
@ -586,7 +558,7 @@ u8 Camera::I2C_Read(bool last)
return ret;
}
void Camera::I2C_Write(u8 val, bool last)
void DSi_Camera::Write(u8 val, bool last)
{
if (DataPos < 2)
{
@ -615,7 +587,7 @@ void Camera::I2C_Write(u8 val, bool last)
else DataPos++;
}
u16 Camera::I2C_ReadReg(u16 addr)
u16 DSi_Camera::I2C_ReadReg(u16 addr)
{
switch (addr)
{
@ -651,7 +623,7 @@ u16 Camera::I2C_ReadReg(u16 addr)
return 0;
}
void Camera::I2C_WriteReg(u16 addr, u16 val)
void DSi_Camera::I2C_WriteReg(u16 addr, u16 val)
{
switch (addr)
{
@ -720,14 +692,14 @@ void Camera::I2C_WriteReg(u16 addr, u16 val)
// TODO: not sure at all what is the accessible range
// or if there is any overlap in the address range
u8 Camera::MCU_Read(u16 addr)
u8 DSi_Camera::MCU_Read(u16 addr)
{
addr &= 0x7FFF;
return MCURegs[addr];
}
void Camera::MCU_Write(u16 addr, u8 val)
void DSi_Camera::MCU_Write(u16 addr, u8 val)
{
addr &= 0x7FFF;
@ -749,7 +721,7 @@ void Camera::MCU_Write(u16 addr, u8 val)
}
void Camera::InputFrame(u32* data, int width, int height, bool rgb)
void DSi_Camera::InputFrame(u32* data, int width, int height, bool rgb)
{
// TODO: double-buffering?
@ -820,19 +792,3 @@ void Camera::InputFrame(u32* data, int width, int height, bool rgb)
}
}
}
}

View File

@ -21,38 +21,15 @@
#include "types.h"
#include "Savestate.h"
#include "DSi_I2C.h"
namespace DSi_CamModule
{
class DSi_CamModule;
class Camera;
extern Camera* Camera0;
extern Camera* Camera1;
bool Init();
void DeInit();
void Reset();
void Stop();
void DoSavestate(Savestate* file);
void IRQ(u32 param);
void TransferScanline(u32 line);
u8 Read8(u32 addr);
u16 Read16(u32 addr);
u32 Read32(u32 addr);
void Write8(u32 addr, u8 val);
void Write16(u32 addr, u16 val);
void Write32(u32 addr, u32 val);
class Camera
class DSi_Camera : public DSi_I2CDevice
{
public:
Camera(u32 num);
~Camera();
DSi_Camera(DSi_I2CHost* host, u32 num);
~DSi_Camera();
void DoSavestate(Savestate* file);
@ -66,9 +43,9 @@ public:
// lengths in words
int TransferScanline(u32* buffer, int maxlen);
void I2C_Start();
u8 I2C_Read(bool last);
void I2C_Write(u8 val, bool last);
void Acquire();
u8 Read(bool last);
void Write(u8 val, bool last);
void InputFrame(u32* data, int width, int height, bool rgb);
@ -101,6 +78,47 @@ private:
u32 FrameBuffer[640*480/2]; // YUYV framebuffer, two pixels per word
};
}
class DSi_CamModule
{
public:
DSi_CamModule();
~DSi_CamModule();
void Reset();
void Stop();
void DoSavestate(Savestate* file);
DSi_Camera* GetOuterCamera() { return Camera0; }
DSi_Camera* GetInnerCamera() { return Camera1; }
void IRQ(u32 param);
void TransferScanline(u32 line);
u8 Read8(u32 addr);
u16 Read16(u32 addr);
u32 Read32(u32 addr);
void Write8(u32 addr, u8 val);
void Write16(u32 addr, u16 val);
void Write32(u32 addr, u32 val);
private:
DSi_Camera* Camera0; // 78 / facing outside
DSi_Camera* Camera1; // 7A / selfie cam
u16 ModuleCnt;
u16 Cnt;
u32 CropStart, CropEnd;
// pixel data buffer holds a maximum of 512 words, regardless of how long scanlines are
u32 DataBuffer[512];
u32 BufferReadPos, BufferWritePos;
u32 BufferNumLines;
DSi_Camera* CurCamera;
static const u32 kIRQInterval;
static const u32 kTransferStart;
};
#endif // DSI_CAMERA_H

View File

@ -29,18 +29,16 @@
using Platform::Log;
using Platform::LogLevel;
namespace DSi_BPTWL
{
// TODO: These are purely approximations
const double PowerButtonShutdownTime = 0.5;
const double PowerButtonForcedShutdownTime = 5.0;
const double VolumeSwitchRepeatStart = 0.5;
const double VolumeSwitchRepeatRate = 1.0 / 6;
const double DSi_BPTWL::PowerButtonShutdownTime = 0.5;
const double DSi_BPTWL::PowerButtonForcedShutdownTime = 5.0;
const double DSi_BPTWL::VolumeSwitchRepeatStart = 0.5;
const double DSi_BPTWL::VolumeSwitchRepeatRate = 1.0 / 6;
// Could not find a pattern or a decent formula for these,
// regardless, they're only 64 bytes in size
const u8 VolumeDownTable[32] =
const u8 DSi_BPTWL::VolumeDownTable[32] =
{
0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x03,
0x04, 0x05, 0x06, 0x06, 0x07, 0x08, 0x09, 0x0A,
@ -48,7 +46,7 @@ const u8 VolumeDownTable[32] =
0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A,
};
const u8 VolumeUpTable[32] =
const u8 DSi_BPTWL::VolumeUpTable[32] =
{
0x02, 0x03, 0x06, 0x07, 0x08, 0x0A, 0x0B, 0x0C,
0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14,
@ -56,27 +54,16 @@ const u8 VolumeUpTable[32] =
0x1D, 0x1E, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F,
};
double PowerButtonTime = 0.0;
bool PowerButtonDownFlag = false;
bool PowerButtonShutdownFlag = false;
double VolumeSwitchTime = 0.0;
double VolumeSwitchRepeatTime = 0.0;
bool VolumeSwitchDownFlag = false;
u32 VolumeSwitchKeysDown = 0;
u8 Registers[0x100];
u32 CurPos;
bool Init()
{
return true;
}
void DeInit()
DSi_BPTWL::DSi_BPTWL(DSi_I2CHost* host) : DSi_I2CDevice(host)
{
}
void Reset()
DSi_BPTWL::~DSi_BPTWL()
{
}
void DSi_BPTWL::Reset()
{
CurPos = -1;
memset(Registers, 0x5A, 0x100);
@ -115,10 +102,11 @@ void Reset()
VolumeSwitchTime = 0.0;
VolumeSwitchRepeatTime = 0.0;
VolumeSwitchKeysDown = 0;
VolumeSwitchDownFlag = false;
}
void DoSavestate(Savestate* file)
void DSi_BPTWL::DoSavestate(Savestate* file)
{
file->Section("I2BP");
@ -127,21 +115,21 @@ void DoSavestate(Savestate* file)
}
// TODO: Needs more investigation on the other bits
inline bool GetIRQMode()
inline bool DSi_BPTWL::GetIRQMode()
{
return Registers[0x12] & 0x01;
}
u8 GetBootFlag() { return Registers[0x70]; }
u8 DSi_BPTWL::GetBootFlag() { return Registers[0x70]; }
bool GetBatteryCharging() { return Registers[0x20] >> 7; }
void SetBatteryCharging(bool charging)
bool DSi_BPTWL::GetBatteryCharging() { return Registers[0x20] >> 7; }
void DSi_BPTWL::SetBatteryCharging(bool charging)
{
Registers[0x20] = (((charging ? 0x8 : 0x0) << 4) | (Registers[0x20] & 0x0F));
}
u8 GetBatteryLevel() { return Registers[0x20] & 0xF; }
void SetBatteryLevel(u8 batteryLevel)
u8 DSi_BPTWL::GetBatteryLevel() { return Registers[0x20] & 0xF; }
void DSi_BPTWL::SetBatteryLevel(u8 batteryLevel)
{
Registers[0x20] = ((Registers[0x20] & 0xF0) | (batteryLevel & 0x0F));
//SPI_Powerman::SetBatteryLevelOkay(batteryLevel > batteryLevel_Low ? true : false);
@ -153,20 +141,20 @@ void SetBatteryLevel(u8 batteryLevel)
}
u8 GetVolumeLevel() { return Registers[0x40]; }
void SetVolumeLevel(u8 volume)
u8 DSi_BPTWL::GetVolumeLevel() { return Registers[0x40]; }
void DSi_BPTWL::SetVolumeLevel(u8 volume)
{
Registers[0x40] = volume & 0x1F;
}
u8 GetBacklightLevel() { return Registers[0x41]; }
void SetBacklightLevel(u8 backlight)
u8 DSi_BPTWL::GetBacklightLevel() { return Registers[0x41]; }
void DSi_BPTWL::SetBacklightLevel(u8 backlight)
{
Registers[0x41] = backlight > 4 ? 4 : backlight;
}
void ResetButtonState()
void DSi_BPTWL::ResetButtonState()
{
PowerButtonTime = 0.0;
PowerButtonDownFlag = false;
@ -178,7 +166,7 @@ void ResetButtonState()
VolumeSwitchRepeatTime = 0.0;
}
void DoHardwareReset(bool direct)
void DSi_BPTWL::DoHardwareReset(bool direct)
{
ResetButtonState();
@ -196,14 +184,14 @@ void DoHardwareReset(bool direct)
NDS::ARM7->Halt(4);
}
void DoShutdown()
void DSi_BPTWL::DoShutdown()
{
ResetButtonState();
NDS::Stop(Platform::StopReason::PowerOff);
}
void SetPowerButtonHeld(double time)
void DSi_BPTWL::SetPowerButtonHeld(double time)
{
if (!PowerButtonDownFlag)
{
@ -230,7 +218,7 @@ void SetPowerButtonHeld(double time)
}
}
void SetPowerButtonReleased(double time)
void DSi_BPTWL::SetPowerButtonReleased(double time)
{
double elapsed = time - PowerButtonTime;
if (elapsed >= 0 && elapsed < PowerButtonShutdownTime)
@ -243,12 +231,12 @@ void SetPowerButtonReleased(double time)
PowerButtonShutdownFlag = false;
}
void SetVolumeSwitchHeld(u32 key)
void DSi_BPTWL::SetVolumeSwitchHeld(u32 key)
{
VolumeSwitchKeysDown |= (1 << key);
}
void SetVolumeSwitchReleased(u32 key)
void DSi_BPTWL::SetVolumeSwitchReleased(u32 key)
{
VolumeSwitchKeysDown &= ~(1 << key);
VolumeSwitchDownFlag = false;
@ -256,7 +244,7 @@ void SetVolumeSwitchReleased(u32 key)
VolumeSwitchRepeatTime = 0.0;
}
inline bool CheckVolumeSwitchKeysValid()
inline bool DSi_BPTWL::CheckVolumeSwitchKeysValid()
{
bool up = VolumeSwitchKeysDown & (1 << volumeKey_Up);
bool down = VolumeSwitchKeysDown & (1 << volumeKey_Down);
@ -264,7 +252,7 @@ inline bool CheckVolumeSwitchKeysValid()
return up != down;
}
s32 ProcessVolumeSwitchInput(double time)
s32 DSi_BPTWL::ProcessVolumeSwitchInput(double time)
{
if (!CheckVolumeSwitchKeysValid())
return -1;
@ -303,7 +291,7 @@ s32 ProcessVolumeSwitchInput(double time)
}
void DoPowerButtonPress()
void DSi_BPTWL::DoPowerButtonPress()
{
// Set button pressed IRQ
SetIRQ(IRQ_PowerButtonPressed);
@ -311,7 +299,7 @@ void DoPowerButtonPress()
// There is no default hardware behavior for pressing the power button
}
void DoPowerButtonReset()
void DSi_BPTWL::DoPowerButtonReset()
{
// Reset via IRQ, handled by software
SetIRQ(IRQ_PowerButtonReset);
@ -324,7 +312,7 @@ void DoPowerButtonReset()
}
}
void DoPowerButtonShutdown()
void DSi_BPTWL::DoPowerButtonShutdown()
{
// Shutdown via IRQ, handled by software
if (!PowerButtonShutdownFlag)
@ -346,12 +334,12 @@ void DoPowerButtonShutdown()
// down the power button, the DSi will still shut down
}
void DoPowerButtonForceShutdown()
void DSi_BPTWL::DoPowerButtonForceShutdown()
{
DoShutdown();
}
void DoVolumeSwitchPress(u32 key)
void DSi_BPTWL::DoVolumeSwitchPress(u32 key)
{
u8 volume = Registers[0x40];
@ -373,7 +361,7 @@ void DoVolumeSwitchPress(u32 key)
SetIRQ(IRQ_VolumeSwitchPressed);
}
void SetIRQ(u8 irqFlag)
void DSi_BPTWL::SetIRQ(u8 irqFlag)
{
Registers[0x10] |= irqFlag & IRQ_ValidMask;
@ -383,12 +371,12 @@ void SetIRQ(u8 irqFlag)
}
}
void Start()
void DSi_BPTWL::Acquire()
{
//printf("BPTWL: start\n");
}
u8 Read(bool last)
u8 DSi_BPTWL::Read(bool last)
{
//printf("BPTWL: read %02X -> %02X @ %08X\n", CurPos, Registers[CurPos], NDS::GetPC(1));
u8 ret = Registers[CurPos];
@ -409,7 +397,7 @@ u8 Read(bool last)
return ret;
}
void Write(u8 val, bool last)
void DSi_BPTWL::Write(u8 val, bool last)
{
if (last)
{
@ -460,51 +448,69 @@ void Write(u8 val, bool last)
CurPos++; // CHECKME
}
DSi_I2CHost::DSi_I2CHost()
{
BPTWL = new DSi_BPTWL(this);
Camera0 = new DSi_Camera(this, 0);
Camera1 = new DSi_Camera(this, 1);
}
namespace DSi_I2C
DSi_I2CHost::~DSi_I2CHost()
{
u8 Cnt;
u8 Data;
u32 Device;
bool Init()
{
if (!DSi_BPTWL::Init()) return false;
return true;
delete BPTWL; BPTWL = nullptr;
delete Camera0; Camera0 = nullptr;
delete Camera1; Camera1 = nullptr;
}
void DeInit()
{
DSi_BPTWL::DeInit();
}
void Reset()
void DSi_I2CHost::Reset()
{
Cnt = 0;
Data = 0;
Device = -1;
CurDeviceID = 0;
CurDevice = nullptr;
DSi_BPTWL::Reset();
BPTWL->Reset();
Camera0->Reset();
Camera1->Reset();
}
void DoSavestate(Savestate* file)
void DSi_I2CHost::DoSavestate(Savestate* file)
{
file->Section("I2Ci");
file->Var8(&Cnt);
file->Var8(&Data);
file->Var32(&Device);
file->Var8(&CurDeviceID);
DSi_BPTWL::DoSavestate(file);
if (!file->Saving)
{
GetCurDevice();
}
BPTWL->DoSavestate(file);
Camera0->DoSavestate(file);
Camera1->DoSavestate(file);
}
void WriteCnt(u8 val)
void DSi_I2CHost::GetCurDevice()
{
switch (CurDeviceID)
{
case 0x4A: CurDevice = BPTWL; break;
case 0x78: CurDevice = Camera0; break;
case 0x7A: CurDevice = Camera1; break;
case 0xA0:
case 0xE0: CurDevice = nullptr; break;
default:
Log(LogLevel::Warn, "I2C: unknown device %02X\n", CurDeviceID);
CurDevice = nullptr;
break;
}
}
void DSi_I2CHost::WriteCnt(u8 val)
{
//printf("I2C: write CNT %02X, %02X, %08X\n", val, Data, NDS::GetPC(1));
@ -522,17 +528,13 @@ void WriteCnt(u8 val)
// read
val &= 0xF7;
switch (Device)
if (CurDevice)
{
Data = CurDevice->Read(islast);
}
else
{
case 0x4A: Data = DSi_BPTWL::Read(islast); break;
case 0x78: Data = DSi_CamModule::Camera0->I2C_Read(islast); break;
case 0x7A: Data = DSi_CamModule::Camera1->I2C_Read(islast); break;
case 0xA0:
case 0xE0: Data = 0xFF; break;
default:
Log(LogLevel::Warn, "I2C: read on unknown device %02X, cnt=%02X, data=%02X, last=%d\n", Device, val, 0, islast);
Data = 0xFF;
break;
}
//printf("I2C read, device=%02X, cnt=%02X, data=%02X, last=%d\n", Device, val, Data, islast);
@ -545,37 +547,30 @@ void WriteCnt(u8 val)
if (val & (1<<1))
{
Device = Data & 0xFE;
CurDeviceID = Data & 0xFE;
//printf("I2C: %s start, device=%02X\n", (Data&0x01)?"read":"write", Device);
switch (Device)
GetCurDevice();
if (CurDevice)
{
CurDevice->Acquire();
}
else
{
case 0x4A: DSi_BPTWL::Start(); break;
case 0x78: DSi_CamModule::Camera0->I2C_Start(); break;
case 0x7A: DSi_CamModule::Camera1->I2C_Start(); break;
case 0xA0:
case 0xE0: ack = false; break;
default:
Log(LogLevel::Warn, "I2C: %s start on unknown device %02X\n", (Data&0x01)?"read":"write", Device);
ack = false;
break;
}
}
else
{
//printf("I2C write, device=%02X, cnt=%02X, data=%02X, last=%d\n", Device, val, Data, islast);
switch (Device)
if (CurDevice)
{
CurDevice->Write(Data, islast);
}
else
{
case 0x4A: DSi_BPTWL::Write(Data, islast); break;
case 0x78: DSi_CamModule::Camera0->I2C_Write(Data, islast); break;
case 0x7A: DSi_CamModule::Camera1->I2C_Write(Data, islast); break;
case 0xA0:
case 0xE0: ack = false; break;
default:
Log(LogLevel::Warn, "I2C: write on unknown device %02X, cnt=%02X, data=%02X, last=%d\n", Device, val, Data, islast);
ack = false;
break;
}
}
@ -588,14 +583,12 @@ void WriteCnt(u8 val)
Cnt = val;
}
u8 ReadData()
u8 DSi_I2CHost::ReadData()
{
return Data;
}
void WriteData(u8 val)
void DSi_I2CHost::WriteData(u8 val)
{
Data = val;
}
}

View File

@ -22,95 +22,162 @@
#include "types.h"
#include "Savestate.h"
namespace DSi_BPTWL
class DSi_I2CHost;
class DSi_Camera;
class DSi_I2CDevice
{
public:
DSi_I2CDevice(DSi_I2CHost* host) : Host(host) {}
virtual ~DSi_I2CDevice() {}
virtual void Reset() = 0;
virtual void DoSavestate(Savestate* file) = 0;
u8 GetBootFlag();
virtual void Acquire() = 0;
virtual u8 Read(bool last) = 0;
virtual void Write(u8 val, bool last) = 0;
bool GetBatteryCharging();
void SetBatteryCharging(bool charging);
enum
{
batteryLevel_Critical = 0x0,
batteryLevel_AlmostEmpty = 0x1,
batteryLevel_Low = 0x3,
batteryLevel_Half = 0x7,
batteryLevel_ThreeQuarters = 0xB,
batteryLevel_Full = 0xF
protected:
DSi_I2CHost* Host;
};
u8 GetBatteryLevel();
void SetBatteryLevel(u8 batteryLevel);
// 0-31
u8 GetVolumeLevel();
void SetVolumeLevel(u8 volume);
// 0-4
u8 GetBacklightLevel();
void SetBacklightLevel(u8 backlight);
void DoHardwareReset(bool direct);
void DoShutdown();
enum
class DSi_BPTWL : public DSi_I2CDevice
{
volumeKey_Up,
volumeKey_Down,
public:
enum
{
batteryLevel_Critical = 0x0,
batteryLevel_AlmostEmpty = 0x1,
batteryLevel_Low = 0x3,
batteryLevel_Half = 0x7,
batteryLevel_ThreeQuarters = 0xB,
batteryLevel_Full = 0xF
};
enum
{
volumeKey_Up,
volumeKey_Down,
};
enum
{
IRQ_PowerButtonReset = 0x01, // Triggered after releasing the power button quickly
IRQ_PowerButtonShutdown = 0x02, // Triggered after holding the power button for less than a second
IRQ_PowerButtonPressed = 0x08, // Triggered after pressing the power button
IRQ_BatteryEmpty = 0x10, //
IRQ_BatteryLow = 0x20, // Triggered when the battery level reaches 1
IRQ_VolumeSwitchPressed = 0x40, // Triggered once when the volume sliders are first pressed and repeatedly when held down
/*
Bit 2 (0x04) could be set when holding the power button for more than 5 seconds? (forced power off)
It is unknown whether it is set as the console powers off immediately.
Bit 7 (0x80) is unused?
Both bits are never used by the official ARM7 libraries, but could have some undocumented hardware functionality (?).
*/
IRQ_ValidMask = 0x7B,
};
DSi_BPTWL(DSi_I2CHost* host);
~DSi_BPTWL() override;
void Reset() override;
void DoSavestate(Savestate* file) override;
u8 GetBootFlag();
bool GetBatteryCharging();
void SetBatteryCharging(bool charging);
u8 GetBatteryLevel();
void SetBatteryLevel(u8 batteryLevel);
// 0-31
u8 GetVolumeLevel();
void SetVolumeLevel(u8 volume);
// 0-4
u8 GetBacklightLevel();
void SetBacklightLevel(u8 backlight);
void DoHardwareReset(bool direct);
void DoShutdown();
// Used by hotkeys
void SetPowerButtonHeld(double time);
void SetPowerButtonReleased(double time);
void SetVolumeSwitchHeld(u32 key);
void SetVolumeSwitchReleased(u32 key);
s32 ProcessVolumeSwitchInput(double time);
void DoPowerButtonPress();
void DoPowerButtonReset();
void DoPowerButtonShutdown();
void DoPowerButtonForceShutdown();
void DoVolumeSwitchPress(u32 key);
void SetIRQ(u8 irqFlag);
void Acquire() override;
u8 Read(bool last) override;
void Write(u8 val, bool last) override;
private:
static const double PowerButtonShutdownTime;
static const double PowerButtonForcedShutdownTime;
static const double VolumeSwitchRepeatStart;
static const double VolumeSwitchRepeatRate;
static const u8 VolumeDownTable[32];
static const u8 VolumeUpTable[32];
double PowerButtonTime;
bool PowerButtonDownFlag;
bool PowerButtonShutdownFlag;
double VolumeSwitchTime;
double VolumeSwitchRepeatTime;
bool VolumeSwitchDownFlag ;
u32 VolumeSwitchKeysDown;
u8 Registers[0x100];
u32 CurPos;
bool GetIRQMode();
void ResetButtonState();
bool CheckVolumeSwitchKeysValid();
};
// Used by hotkeys
void SetPowerButtonHeld(double time);
void SetPowerButtonReleased(double time);
void SetVolumeSwitchHeld(u32 key);
void SetVolumeSwitchReleased(u32 key);
s32 ProcessVolumeSwitchInput(double time);
void DoPowerButtonPress();
void DoPowerButtonReset();
void DoPowerButtonShutdown();
void DoPowerButtonForceShutdown();
void DoVolumeSwitchPress(u32 key);
enum
class DSi_I2CHost
{
IRQ_PowerButtonReset = 0x01, // Triggered after releasing the power button quickly
IRQ_PowerButtonShutdown = 0x02, // Triggered after holding the power button for less than a second
IRQ_PowerButtonPressed = 0x08, // Triggered after pressing the power button
IRQ_BatteryEmpty = 0x10, //
IRQ_BatteryLow = 0x20, // Triggered when the battery level reaches 1
IRQ_VolumeSwitchPressed = 0x40, // Triggered once when the volume sliders are first pressed and repeatedly when held down
/*
Bit 2 (0x04) could be set when holding the power button for more than 5 seconds? (forced power off)
It is unknown whether it is set as the console powers off immediately.
Bit 7 (0x80) is unused?
Both bits are never used by the official ARM7 libraries, but could have some undocumented hardware functionality (?).
*/
IRQ_ValidMask = 0x7B,
public:
DSi_I2CHost();
~DSi_I2CHost();
void Reset();
void DoSavestate(Savestate* file);
DSi_BPTWL* GetBPTWL() { return BPTWL; }
DSi_Camera* GetOuterCamera() { return Camera0; }
DSi_Camera* GetInnerCamera() { return Camera1; }
u8 ReadCnt() { return Cnt; }
void WriteCnt(u8 val);
u8 ReadData();
void WriteData(u8 val);
private:
u8 Cnt;
u8 Data;
DSi_BPTWL* BPTWL; // 4A / BPTWL IC
DSi_Camera* Camera0; // 78 / facing outside
DSi_Camera* Camera1; // 7A / selfie cam
u8 CurDeviceID;
DSi_I2CDevice* CurDevice;
void GetCurDevice();
};
void SetIRQ(u8 irqFlag);
}
namespace DSi_I2C
{
extern u8 Cnt;
bool Init();
void DeInit();
void Reset();
void DoSavestate(Savestate* file);
void WriteCnt(u8 val);
u8 ReadData();
void WriteData(u8 val);
//void TransferDone(u32 param);
}
#endif // DSI_I2C_H

View File

@ -1365,8 +1365,8 @@ void CamInputFrame(int cam, u32* data, int width, int height, bool rgb)
{
switch (cam)
{
case 0: return DSi_CamModule::Camera0->InputFrame(data, width, height, rgb);
case 1: return DSi_CamModule::Camera1->InputFrame(data, width, height, rgb);
case 0: return DSi::CamModule->GetOuterCamera()->InputFrame(data, width, height, rgb);
case 1: return DSi::CamModule->GetInnerCamera()->InputFrame(data, width, height, rgb);
}
}
}

View File

@ -46,9 +46,7 @@ class SPIDevice
public:
SPIDevice(SPIHost* host) : Host(host), Hold(false), DataPos(0) {}
virtual ~SPIDevice() {}
virtual void Reset() = 0;
virtual void DoSavestate(Savestate* file) = 0;
virtual u8 Read() { return Data; }
@ -68,9 +66,7 @@ class FirmwareMem : public SPIDevice
public:
FirmwareMem(SPIHost* host);
~FirmwareMem() override;
void Reset() override;
void DoSavestate(Savestate* file) override;
void SetupDirectBoot(bool dsi);
@ -100,9 +96,7 @@ class PowerMan : public SPIDevice
public:
PowerMan(SPIHost* host);
~PowerMan() override;
void Reset() override;
void DoSavestate(Savestate* file) override;
bool GetBatteryLevelOkay();
@ -122,9 +116,7 @@ class TSC : public SPIDevice
public:
TSC(SPIHost* host);
virtual ~TSC() override;
virtual void Reset() override;
virtual void DoSavestate(Savestate* file) override;
virtual void SetTouchCoords(u16 x, u16 y);
@ -149,9 +141,7 @@ class SPIHost
public:
SPIHost();
~SPIHost();
void Reset();
void DoSavestate(Savestate* file);
FirmwareMem* GetFirmwareMem() { return (FirmwareMem*)Devices[SPIDevice_FirmwareMem]; }

View File

@ -24,6 +24,7 @@
#include "Platform.h"
#include "Config.h"
#include "NDS.h"
#include "DSi.h"
#include "DSi_I2C.h"
#include "AudioSettingsDialog.h"
@ -126,7 +127,7 @@ void AudioSettingsDialog::onSyncVolumeLevel()
if (Config::DSiVolumeSync && NDS::ConsoleType == 1)
{
bool state = ui->slVolume->blockSignals(true);
ui->slVolume->setValue(DSi_BPTWL::GetVolumeLevel());
ui->slVolume->setValue(DSi::I2C->GetBPTWL()->GetVolumeLevel());
ui->slVolume->blockSignals(state);
}
}
@ -181,7 +182,7 @@ void AudioSettingsDialog::on_slVolume_valueChanged(int val)
{
if (Config::DSiVolumeSync && NDS::ConsoleType == 1)
{
DSi_BPTWL::SetVolumeLevel(val);
DSi::I2C->GetBPTWL()->SetVolumeLevel(val);
return;
}
@ -196,7 +197,7 @@ void AudioSettingsDialog::on_chkSyncDSiVolume_clicked(bool checked)
if (Config::DSiVolumeSync && NDS::ConsoleType == 1)
{
ui->slVolume->setMaximum(31);
ui->slVolume->setValue(DSi_BPTWL::GetVolumeLevel());
ui->slVolume->setValue(DSi::I2C->GetBPTWL()->GetVolumeLevel());
ui->slVolume->setPageStep(4);
ui->slVolume->setTickPosition(QSlider::TicksBelow);
}

View File

@ -22,6 +22,7 @@
#include "SPI.h"
#include "DSi_I2C.h"
#include "NDS.h"
#include "DSi.h"
#include "Config.h"
#include "Platform.h"
@ -42,8 +43,8 @@ PowerManagementDialog::PowerManagementDialog(QWidget* parent) : QDialog(parent),
{
ui->grpDSBattery->setEnabled(false);
oldDSiBatteryLevel = DSi_BPTWL::GetBatteryLevel();
oldDSiBatteryCharging = DSi_BPTWL::GetBatteryCharging();
oldDSiBatteryLevel = DSi::I2C->GetBPTWL()->GetBatteryLevel();
oldDSiBatteryCharging = DSi::I2C->GetBPTWL()->GetBatteryCharging();
}
else
{
@ -54,9 +55,9 @@ PowerManagementDialog::PowerManagementDialog(QWidget* parent) : QDialog(parent),
updateDSBatteryLevelControls();
ui->cbDSiBatteryCharging->setChecked(DSi_BPTWL::GetBatteryCharging());
ui->cbDSiBatteryCharging->setChecked(DSi::I2C->GetBPTWL()->GetBatteryCharging());
int dsiBatterySliderPos;
switch (DSi_BPTWL::GetBatteryLevel())
switch (DSi::I2C->GetBPTWL()->GetBatteryLevel())
{
case DSi_BPTWL::batteryLevel_AlmostEmpty: dsiBatterySliderPos = 0; break;
case DSi_BPTWL::batteryLevel_Low: dsiBatterySliderPos = 1; break;
@ -86,8 +87,8 @@ void PowerManagementDialog::done(int r)
{
if (NDS::ConsoleType == 1)
{
Config::DSiBatteryLevel = DSi_BPTWL::GetBatteryLevel();
Config::DSiBatteryCharging = DSi_BPTWL::GetBatteryCharging();
Config::DSiBatteryLevel = DSi::I2C->GetBPTWL()->GetBatteryLevel();
Config::DSiBatteryCharging = DSi::I2C->GetBPTWL()->GetBatteryCharging();
}
else
{
@ -98,8 +99,8 @@ void PowerManagementDialog::done(int r)
{
if (NDS::ConsoleType == 1)
{
DSi_BPTWL::SetBatteryLevel(oldDSiBatteryLevel);
DSi_BPTWL::SetBatteryCharging(oldDSiBatteryCharging);
DSi::I2C->GetBPTWL()->SetBatteryLevel(oldDSiBatteryLevel);
DSi::I2C->GetBPTWL()->SetBatteryCharging(oldDSiBatteryCharging);
}
else
{
@ -132,7 +133,7 @@ void PowerManagementDialog::updateDSBatteryLevelControls()
void PowerManagementDialog::on_cbDSiBatteryCharging_toggled()
{
DSi_BPTWL::SetBatteryCharging(ui->cbDSiBatteryCharging->isChecked());
DSi::I2C->GetBPTWL()->SetBatteryCharging(ui->cbDSiBatteryCharging->isChecked());
}
void PowerManagementDialog::on_sliderDSiBatteryLevel_valueChanged(int value)
@ -142,13 +143,13 @@ void PowerManagementDialog::on_sliderDSiBatteryLevel_valueChanged(int value)
u8 newBatteryLevel;
switch (value)
{
case 0: newBatteryLevel = DSi_BPTWL::batteryLevel_AlmostEmpty; break;
case 1: newBatteryLevel = DSi_BPTWL::batteryLevel_Low; break;
case 2: newBatteryLevel = DSi_BPTWL::batteryLevel_Half; break;
case 3: newBatteryLevel = DSi_BPTWL::batteryLevel_ThreeQuarters; break;
case 4: newBatteryLevel = DSi_BPTWL::batteryLevel_Full; break;
case 0: newBatteryLevel = DSi::I2C->GetBPTWL()->batteryLevel_AlmostEmpty; break;
case 1: newBatteryLevel = DSi::I2C->GetBPTWL()->batteryLevel_Low; break;
case 2: newBatteryLevel = DSi::I2C->GetBPTWL()->batteryLevel_Half; break;
case 3: newBatteryLevel = DSi::I2C->GetBPTWL()->batteryLevel_ThreeQuarters; break;
case 4: newBatteryLevel = DSi::I2C->GetBPTWL()->batteryLevel_Full; break;
}
DSi_BPTWL::SetBatteryLevel(newBatteryLevel);
DSi::I2C->GetBPTWL()->SetBatteryLevel(newBatteryLevel);
updateDSBatteryLevelControls();
}

View File

@ -583,8 +583,8 @@ void SetBatteryLevels()
{
if (NDS::ConsoleType == 1)
{
DSi_BPTWL::SetBatteryLevel(Config::DSiBatteryLevel);
DSi_BPTWL::SetBatteryCharging(Config::DSiBatteryCharging);
DSi::I2C->GetBPTWL()->SetBatteryLevel(Config::DSiBatteryLevel);
DSi::I2C->GetBPTWL()->SetBatteryCharging(Config::DSiBatteryCharging);
}
else
{

View File

@ -90,8 +90,9 @@
#include "Platform.h"
#include "LocalMP.h"
#include "Config.h"
#include "DSi_I2C.h"
#include "RTC.h"
#include "DSi.h"
#include "DSi_I2C.h"
#include "Savestate.h"
@ -409,33 +410,33 @@ void EmuThread::run()
// Handle power button
if (Input::HotkeyDown(HK_PowerButton))
{
DSi_BPTWL::SetPowerButtonHeld(currentTime);
DSi::I2C->GetBPTWL()->SetPowerButtonHeld(currentTime);
}
else if (Input::HotkeyReleased(HK_PowerButton))
{
DSi_BPTWL::SetPowerButtonReleased(currentTime);
DSi::I2C->GetBPTWL()->SetPowerButtonReleased(currentTime);
}
// Handle volume buttons
if (Input::HotkeyDown(HK_VolumeUp))
{
DSi_BPTWL::SetVolumeSwitchHeld(DSi_BPTWL::volumeKey_Up);
DSi::I2C->GetBPTWL()->SetVolumeSwitchHeld(DSi::I2C->GetBPTWL()->volumeKey_Up);
}
else if (Input::HotkeyReleased(HK_VolumeUp))
{
DSi_BPTWL::SetVolumeSwitchReleased(DSi_BPTWL::volumeKey_Up);
DSi::I2C->GetBPTWL()->SetVolumeSwitchReleased(DSi::I2C->GetBPTWL()->volumeKey_Up);
}
if (Input::HotkeyDown(HK_VolumeDown))
{
DSi_BPTWL::SetVolumeSwitchHeld(DSi_BPTWL::volumeKey_Down);
DSi::I2C->GetBPTWL()->SetVolumeSwitchHeld(DSi::I2C->GetBPTWL()->volumeKey_Down);
}
else if (Input::HotkeyReleased(HK_VolumeDown))
{
DSi_BPTWL::SetVolumeSwitchReleased(DSi_BPTWL::volumeKey_Down);
DSi::I2C->GetBPTWL()->SetVolumeSwitchReleased(DSi::I2C->GetBPTWL()->volumeKey_Down);
}
DSi_BPTWL::ProcessVolumeSwitchInput(currentTime);
DSi::I2C->GetBPTWL()->ProcessVolumeSwitchInput(currentTime);
}
if (EmuRunning == emuStatus_Running || EmuRunning == emuStatus_FrameStep)
@ -562,7 +563,7 @@ void EmuThread::run()
if (Config::DSiVolumeSync && NDS::ConsoleType == 1)
{
u8 volumeLevel = DSi_BPTWL::GetVolumeLevel();
u8 volumeLevel = DSi::I2C->GetBPTWL()->GetVolumeLevel();
if (volumeLevel != dsiVolumeLevel)
{
dsiVolumeLevel = volumeLevel;