207 lines
4.1 KiB
C++
207 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/BizConfig.h"
|
|
#include "BizPlatform/BizFile.h"
|
|
#include "BizPlatform/BizLog.h"
|
|
#include "BizFileManager.h"
|
|
|
|
#include <emulibc.h>
|
|
#include <waterboxcore.h>
|
|
|
|
static bool SkipFW;
|
|
static time_t CurTime;
|
|
|
|
struct InitConfig
|
|
{
|
|
bool SkipFW;
|
|
bool HasGBACart;
|
|
bool DSi;
|
|
bool ClearNAND;
|
|
bool LoadDSiWare;
|
|
int ThreeDeeRenderer;
|
|
GPU::RenderSettings RenderSettings;
|
|
};
|
|
|
|
ECL_EXPORT const char* Init(InitConfig* initConfig,
|
|
Platform::ConfigCallbackInterface* configCallbackInterface,
|
|
Platform::FileCallbackInterface* fileCallbackInterface,
|
|
Platform::LogCallback_t logCallback)
|
|
{
|
|
Platform::SetConfigCallbacks(*configCallbackInterface);
|
|
Platform::SetFileCallbacks(*fileCallbackInterface);
|
|
Platform::SetLogCallback(logCallback);
|
|
|
|
SkipFW = initConfig->SkipFW;
|
|
NDS::SetConsoleType(initConfig->DSi);
|
|
|
|
CurTime = 0;
|
|
RTC::RtcCallback = []() { return CurTime; };
|
|
|
|
if (initConfig->DSi)
|
|
{
|
|
if (const char* error = FileManager::InitNAND(initConfig->ClearNAND, initConfig->LoadDSiWare))
|
|
{
|
|
return error;
|
|
}
|
|
}
|
|
|
|
if (!NDS::Init())
|
|
{
|
|
return "Failed to init core!";
|
|
}
|
|
|
|
GPU::InitRenderer(initConfig->ThreeDeeRenderer);
|
|
GPU::SetRenderSettings(initConfig->ThreeDeeRenderer, initConfig->RenderSettings);
|
|
|
|
NDS::LoadBIOS();
|
|
|
|
if (!initConfig->LoadDSiWare)
|
|
{
|
|
if (const char* error = FileManager::InitCarts(initConfig->HasGBACart))
|
|
{
|
|
return error;
|
|
}
|
|
}
|
|
|
|
if (SkipFW || NDS::NeedsDirectBoot())
|
|
{
|
|
NDS::SetupDirectBoot("nds.rom");
|
|
}
|
|
|
|
NDS::Start();
|
|
|
|
return nullptr;
|
|
}
|
|
|
|
struct MyFrameInfo : public FrameInfo
|
|
{
|
|
s64 Time;
|
|
u32 Keys;
|
|
u8 TouchX;
|
|
u8 TouchY;
|
|
s8 MicVolume;
|
|
s8 GBALightSensor;
|
|
bool ConsiderAltLag;
|
|
};
|
|
|
|
static s16 biz_mic_input[735];
|
|
|
|
static bool ValidRange(s8 sensor)
|
|
{
|
|
return (sensor >= 0) && (sensor <= 10);
|
|
}
|
|
|
|
static int sampPos = 0;
|
|
|
|
static void MicFeedNoise(s8 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;
|
|
|
|
if (f->Keys & 0x8000)
|
|
{
|
|
NDS::LoadBIOS();
|
|
if (SkipFW || NDS::NeedsDirectBoot())
|
|
{
|
|
NDS::SetupDirectBoot("nds.rom");
|
|
}
|
|
|
|
NDS::Start();
|
|
}
|
|
|
|
NDS::SetKeyMask(~f->Keys & 0xFFF);
|
|
|
|
if (f->Keys & 0x1000)
|
|
{
|
|
NDS::TouchScreen(f->TouchX, f->TouchY);
|
|
}
|
|
else
|
|
{
|
|
NDS::ReleaseScreen();
|
|
}
|
|
|
|
if (f->Keys & 0x2000)
|
|
{
|
|
NDS::SetLidClosed(false);
|
|
}
|
|
else if (f->Keys & 0x4000)
|
|
{
|
|
NDS::SetLidClosed(true);
|
|
}
|
|
|
|
MicFeedNoise(f->MicVolume);
|
|
NDS::MicInputFrame(biz_mic_input, 735);
|
|
|
|
int sensor = GBACart::SetInput(0, 1);
|
|
if (sensor != -1 && ValidRange(f->GBALightSensor))
|
|
{
|
|
if (sensor > f->GBALightSensor)
|
|
{
|
|
while (GBACart::SetInput(0, 1) != f->GBALightSensor);
|
|
}
|
|
else if (sensor < f->GBALightSensor)
|
|
{
|
|
while (GBACart::SetInput(1, 1) != f->GBALightSensor);
|
|
}
|
|
}
|
|
|
|
CurTime = f->Time;
|
|
|
|
NDS::RunFrame();
|
|
|
|
if (auto softRenderer = dynamic_cast<GPU3D::SoftRenderer*>(GPU3D::CurrentRenderer.get()))
|
|
{
|
|
softRenderer->StopRenderThread();
|
|
}
|
|
|
|
const u32 SingleScreenSize = 256 * 192;
|
|
memcpy(f->VideoBuffer, GPU::Framebuffer[GPU::FrontBuffer][0], SingleScreenSize * sizeof (u32));
|
|
memcpy(f->VideoBuffer + SingleScreenSize, GPU::Framebuffer[GPU::FrontBuffer][1], SingleScreenSize * sizeof (u32));
|
|
|
|
f->Width = 256;
|
|
f->Height = 384;
|
|
|
|
f->Samples = SPU::ReadOutput(f->SoundBuffer);
|
|
if (f->Samples == 0) // hack
|
|
{
|
|
memset(f->SoundBuffer, 0, 737 * 2 * sizeof (u16));
|
|
f->Samples = 737;
|
|
}
|
|
|
|
f->Cycles = NDS::GetSysClockCycles(2);
|
|
|
|
// if we want to consider other lag sources, use that lag flag if we haven't unlagged already
|
|
if (f->ConsiderAltLag && NDS::LagFrameFlag)
|
|
{
|
|
f->Lagged = NDS::AltLagFrameFlag;
|
|
}
|
|
else
|
|
{
|
|
f->Lagged = NDS::LagFrameFlag;
|
|
}
|
|
|
|
RunningFrame = false;
|
|
}
|
|
|
|
ECL_EXPORT u32 GetCallbackCycleOffset()
|
|
{
|
|
return RunningFrame ? NDS::GetSysClockCycles(2) : 0;
|
|
}
|