BizHawk/waterbox/dobie/cinterface.cpp

185 lines
4.3 KiB
C++

#include "../emulibc/emulibc.h"
#include "../emulibc/waterboxcore.h"
#include <stdint.h>
#include "dobiestation/src/core/emulator.hpp"
#include "dobiestation/src/core/iop/cdvd/cdvd_container.hpp"
static size_t cd_length;
static void (*cdcallback)(size_t sector, uint8_t* dest);
static size_t cd_pos;
class DVD: public CDVD_Container
{
virtual bool open(std::string name) override
{
return true;
}
virtual void close() override {}
virtual size_t read(uint8_t* buff, size_t bytes)
{
uint8_t* buff_end = buff + bytes;
if (cd_pos % 2048 != 0)
{
auto offset = cd_pos % 2048;
auto nread = std::min(2048 - offset, bytes);
uint8_t tmp[2048];
cdcallback(cd_pos / 2048, tmp);
memcpy(buff, tmp + offset, nread);
buff += nread;
cd_pos += nread;
}
while (buff_end >= buff + 2048)
{
cdcallback(cd_pos / 2048, buff);
buff += 2048;
cd_pos += 2048;
}
if (buff_end > buff)
{
auto nread = buff_end - buff;
uint8_t tmp[2048];
cdcallback(cd_pos / 2048, tmp);
memcpy(buff, tmp, nread);
cd_pos += nread;
}
return bytes;
}
virtual void seek(size_t pos, std::ios::seekdir whence) override
{
cd_pos = pos * 2048;
}
virtual bool is_open() override
{
return true;
}
virtual size_t get_size() override
{
return cd_length;
}
};
struct MyFrameInfo: public FrameInfo
{
uint32_t Buttons;
uint32_t Axes;
};
Emulator* emu;
struct SyncSettings
{
bool EEJit;
bool VU0Jit;
bool VU1Jit;
};
ECL_EXPORT bool Initialize(
const uint8_t* bios,
size_t cd_length_,
void (*cdcallback_)(size_t sector, uint8_t* dest),
const SyncSettings& syncSettings
)
{
cd_length = cd_length_;
cdcallback = cdcallback_;
emu = new Emulator();
emu->reset();
emu->set_skip_BIOS_hack(LOAD_DISC);
emu->load_BIOS(bios);
emu->load_memcard(0, "MEMCARD0");
if (!emu->load_CDVD_Container("", std::unique_ptr<CDVD_Container>(new DVD())))
return false;
emu->set_ee_mode(syncSettings.EEJit ? JIT : INTERPRETER);
printf("EE Mode: %s\n", syncSettings.EEJit ? "JIT" : "INTERPRETER");
emu->set_vu0_mode(syncSettings.VU0Jit ? JIT : INTERPRETER);
printf("VU0 Mode: %s\n", syncSettings.VU0Jit ? "JIT" : "INTERPRETER");
emu->set_vu1_mode(syncSettings.VU1Jit ? JIT : INTERPRETER);
printf("VU1 Mode: %s\n", syncSettings.VU1Jit ? "JIT" : "INTERPRETER");
emu->set_wav_output(true);
return true;
}
static int16_t* audio_pos;
void hacky_enqueue_audio(stereo_sample s)
{
*audio_pos++ = s.left;
*audio_pos++ = s.right;
}
bool hacky_lag_flag;
void (*hacky_input_callback)();
ECL_EXPORT void FrameAdvance(MyFrameInfo& f)
{
for (auto i = 0; i < 16; i++)
{
if (f.Buttons & 1 << i)
{
emu->press_button((PAD_BUTTON)i);
}
else
{
emu->release_button((PAD_BUTTON)i);
}
}
for (auto i = 0; i < 4; i++)
{
emu->update_joystick((JOYSTICK)(i >> 1), (JOYSTICK_AXIS)(i & 1), f.Axes >> (i * 8));
}
audio_pos = f.SoundBuffer;
hacky_lag_flag = true;
emu->run();
f.Lagged = hacky_lag_flag;
emu->get_inner_resolution(f.Width, f.Height);
{
const uint32_t* src = emu->get_framebuffer();
const uint32_t* srcend = src + f.Width * f.Height;
uint32_t* dst = f.VideoBuffer;
while (src < srcend)
{
*dst = *src;
std::swap(((uint8_t*)dst)[2], ((uint8_t*)dst)[0]);
src++;
dst++;
}
}
f.Samples = (audio_pos - f.SoundBuffer) / 2;
audio_pos = nullptr;
}
ECL_EXPORT void GetMemoryAreas(MemoryArea *m)
{
m[0].Data = emu->RDRAM;
m[0].Name = "RDRAM";
m[0].Size = 1024 * 1024 * 32;
m[0].Flags = MEMORYAREA_FLAGS_WRITABLE | MEMORYAREA_FLAGS_WORDSIZE4 | MEMORYAREA_FLAGS_PRIMARY;
m[1].Data = emu->IOP_RAM;
m[1].Name = "IOP_RAM";
m[1].Size = 1024 * 1024 * 2;
m[1].Flags = MEMORYAREA_FLAGS_WRITABLE | MEMORYAREA_FLAGS_WORDSIZE4;
m[2].Data = emu->BIOS;
m[2].Name = "BIOS";
m[2].Size = 1024 * 1024 * 4;
m[2].Flags = MEMORYAREA_FLAGS_WORDSIZE4;
m[3].Data = emu->SPU_RAM;
m[3].Name = "SPU_RAM";
m[3].Size = 1024 * 1024 * 2;
m[3].Flags = MEMORYAREA_FLAGS_WRITABLE | MEMORYAREA_FLAGS_WORDSIZE4;
m[4].Data = emu->memcard.mem;
m[4].Name = "MEMCARD0";
m[4].Size = 0x840000;
m[4].Flags = MEMORYAREA_FLAGS_WRITABLE | MEMORYAREA_FLAGS_WORDSIZE1 | MEMORYAREA_FLAGS_SAVERAMMABLE;
}
ECL_EXPORT void SetInputCallback(void (*callback)())
{
hacky_input_callback = callback;
}