175 lines
4.1 KiB
C++
175 lines
4.1 KiB
C++
#include "NDS.h"
|
|
#include "GPU.h"
|
|
#include "SPU.h"
|
|
#include "RTC.h"
|
|
#include "GBACart.h"
|
|
#include "frontend/mic_blow.h"
|
|
|
|
#include "BizPlatform/BizOGL.h"
|
|
#include "BizGLPresenter.h"
|
|
|
|
#include <emulibc.h>
|
|
#include <waterboxcore.h>
|
|
|
|
static bool GLPresentation;
|
|
|
|
ECL_EXPORT const char* InitGL(BizOGL::LoadGLProc loadGLProc, int threeDeeRenderer, int scaleFactor, bool isWinApi)
|
|
{
|
|
switch (threeDeeRenderer)
|
|
{
|
|
case 0:
|
|
BizOGL::LoadGL(loadGLProc, BizOGL::LoadGLVersion::V3_1, isWinApi);
|
|
break;
|
|
case 1:
|
|
BizOGL::LoadGL(loadGLProc, BizOGL::LoadGLVersion::V3_2, isWinApi);
|
|
break;
|
|
case 2:
|
|
BizOGL::LoadGL(loadGLProc, BizOGL::LoadGLVersion::V4_3, isWinApi);
|
|
break;
|
|
default:
|
|
return "Unknown 3DRenderer!";
|
|
}
|
|
|
|
GLPresenter::Init(threeDeeRenderer ? scaleFactor : 1);
|
|
GLPresentation = true;
|
|
return nullptr;
|
|
}
|
|
|
|
struct MyFrameInfo : public FrameInfo
|
|
{
|
|
melonDS::NDS* NDS;
|
|
u32 Keys;
|
|
u8 TouchX;
|
|
u8 TouchY;
|
|
u8 MicVolume;
|
|
u8 GBALightSensor;
|
|
bool ConsiderAltLag;
|
|
};
|
|
|
|
static s16 biz_mic_input[735];
|
|
|
|
static int sampPos = 0;
|
|
|
|
static void MicFeedNoise(u8 vol)
|
|
{
|
|
int sampLen = sizeof(mic_blow) / sizeof(*mic_blow);
|
|
|
|
for (int i = 0; i < 735; i++)
|
|
{
|
|
biz_mic_input[i] = round(mic_blow[sampPos++] * (vol / 100.0));
|
|
if (sampPos >= sampLen) sampPos = 0;
|
|
}
|
|
}
|
|
|
|
static bool RunningFrame = false;
|
|
|
|
ECL_EXPORT void FrameAdvance(MyFrameInfo* f)
|
|
{
|
|
RunningFrame = true;
|
|
|
|
f->NDS->SetKeyMask(~f->Keys & 0xFFF);
|
|
|
|
if (f->Keys & 0x1000)
|
|
{
|
|
// move touch coords incrementally to our new touch point
|
|
f->NDS->MoveTouch(f->TouchX, f->TouchY);
|
|
}
|
|
else
|
|
{
|
|
f->NDS->ReleaseScreen();
|
|
}
|
|
|
|
if (f->Keys & 0x2000)
|
|
{
|
|
f->NDS->SetLidClosed(false);
|
|
}
|
|
else if (f->Keys & 0x4000)
|
|
{
|
|
f->NDS->SetLidClosed(true);
|
|
}
|
|
|
|
MicFeedNoise(f->MicVolume);
|
|
f->NDS->MicInputFrame(biz_mic_input, 735);
|
|
|
|
if (auto* gbaCart = f->NDS->GetGBACart())
|
|
{
|
|
int sensor = gbaCart->SetInput(melonDS::GBACart::Input_SolarSensorDown, 1);
|
|
if (sensor != -1)
|
|
{
|
|
if (f->GBALightSensor > 10) f->GBALightSensor = 10;
|
|
|
|
if (sensor > f->GBALightSensor)
|
|
{
|
|
while (gbaCart->SetInput(melonDS::GBACart::Input_SolarSensorDown, 1) != f->GBALightSensor);
|
|
}
|
|
else if (sensor < f->GBALightSensor)
|
|
{
|
|
while (gbaCart->SetInput(melonDS::GBACart::Input_SolarSensorUp, 1) != f->GBALightSensor);
|
|
}
|
|
}
|
|
}
|
|
|
|
f->NDS->RunFrame();
|
|
|
|
if (f->Keys & 0x1000)
|
|
{
|
|
// finalize touch after emulation finishes
|
|
f->NDS->TouchScreen(f->TouchX, f->TouchY);
|
|
}
|
|
|
|
auto& renderer3d = f->NDS->GetRenderer3D();
|
|
if (!renderer3d.Accelerated)
|
|
{
|
|
auto& softRenderer = static_cast<melonDS::SoftRenderer&>(renderer3d);
|
|
softRenderer.StopRenderThread();
|
|
}
|
|
|
|
if (GLPresentation)
|
|
{
|
|
std::tie(f->Width, f->Height) = GLPresenter::Present(f->NDS->GPU);
|
|
}
|
|
else
|
|
{
|
|
constexpr u32 SingleScreenSize = 256 * 192;
|
|
|
|
auto& gpu = f->NDS->GPU;
|
|
memcpy(f->VideoBuffer, gpu.Framebuffer[gpu.FrontBuffer][0].get(), SingleScreenSize * sizeof(u32));
|
|
memcpy(f->VideoBuffer + SingleScreenSize, gpu.Framebuffer[gpu.FrontBuffer][1].get(), SingleScreenSize * sizeof(u32));
|
|
|
|
f->Width = 256;
|
|
f->Height = 384;
|
|
}
|
|
|
|
f->Samples = f->NDS->SPU.ReadOutput(f->SoundBuffer, 4096);
|
|
if (f->Samples == 0) // hack when core decides to stop outputting audio altogether (lid closed or power off)
|
|
{
|
|
memset(f->SoundBuffer, 0, 737 * 2 * sizeof(u16));
|
|
f->Samples = 737;
|
|
}
|
|
|
|
f->Cycles = f->NDS->GetSysClockCycles(2);
|
|
|
|
// if we want to consider other lag sources, use that lag flag if we haven't unlagged already
|
|
if (f->ConsiderAltLag && f->NDS->LagFrameFlag)
|
|
{
|
|
f->Lagged = f->NDS->AltLagFrameFlag;
|
|
}
|
|
else
|
|
{
|
|
f->Lagged = f->NDS->LagFrameFlag;
|
|
}
|
|
|
|
RunningFrame = false;
|
|
}
|
|
|
|
ECL_EXPORT u32 GetCallbackCycleOffset(melonDS::NDS* nds)
|
|
{
|
|
return RunningFrame ? nds->GetSysClockCycles(2) : 0;
|
|
}
|
|
|
|
ECL_EXPORT void SetSoundConfig(melonDS::NDS* nds, int bitDepth, int interpolation)
|
|
{
|
|
nds->SPU.SetDegrade10Bit(static_cast<melonDS::AudioBitDepth>(bitDepth));
|
|
nds->SPU.SetInterpolation(static_cast<melonDS::AudioInterpolation>(interpolation));
|
|
}
|