2022-02-12 02:22:16 +00:00
|
|
|
#include <n64/n64.hpp>
|
|
|
|
|
|
|
|
#include <emulibc.h>
|
|
|
|
#include <waterboxcore.h>
|
2022-02-16 10:15:27 +00:00
|
|
|
|
|
|
|
#include <vector>
|
|
|
|
|
2022-02-12 02:22:16 +00:00
|
|
|
#define EXPORT extern "C" ECL_EXPORT
|
|
|
|
|
|
|
|
typedef enum
|
|
|
|
{
|
|
|
|
Unplugged,
|
|
|
|
Standard,
|
|
|
|
Mempak,
|
|
|
|
Rumblepak,
|
2022-03-21 10:08:23 +00:00
|
|
|
Transferpak,
|
|
|
|
Mouse,
|
2022-02-12 02:22:16 +00:00
|
|
|
} ControllerType;
|
|
|
|
|
|
|
|
typedef enum
|
|
|
|
{
|
|
|
|
UP = 1 << 0,
|
|
|
|
DOWN = 1 << 1,
|
|
|
|
LEFT = 1 << 2,
|
|
|
|
RIGHT = 1 << 3,
|
|
|
|
B = 1 << 4,
|
|
|
|
A = 1 << 5,
|
|
|
|
C_UP = 1 << 6,
|
|
|
|
C_DOWN = 1 << 7,
|
|
|
|
C_LEFT = 1 << 8,
|
|
|
|
C_RIGHT = 1 << 9,
|
|
|
|
L = 1 << 10,
|
|
|
|
R = 1 << 11,
|
|
|
|
Z = 1 << 12,
|
|
|
|
START = 1 << 13,
|
|
|
|
} Buttons_t;
|
|
|
|
|
2022-03-21 10:08:23 +00:00
|
|
|
static u64 biztime = 0;
|
|
|
|
|
|
|
|
static u64 GetBizTime()
|
|
|
|
{
|
|
|
|
return biztime;
|
|
|
|
}
|
|
|
|
|
2022-02-12 02:22:16 +00:00
|
|
|
struct BizPlatform : ares::Platform
|
|
|
|
{
|
|
|
|
auto attach(ares::Node::Object) -> void override;
|
|
|
|
auto pak(ares::Node::Object) -> ares::VFS::Pak override;
|
2022-04-15 05:45:10 +00:00
|
|
|
auto log(string_view) -> void override;
|
2022-02-12 02:22:16 +00:00
|
|
|
auto video(ares::Node::Video::Screen, const u32*, u32, u32, u32) -> void override;
|
2022-03-21 10:08:23 +00:00
|
|
|
auto audio(ares::Node::Audio::Stream) -> void override;
|
2022-02-12 02:22:16 +00:00
|
|
|
auto input(ares::Node::Input::Input) -> void override;
|
|
|
|
|
2022-02-16 10:15:27 +00:00
|
|
|
ares::VFS::Pak bizpak = nullptr;
|
2022-02-12 02:22:16 +00:00
|
|
|
u32* videobuf = nullptr;
|
|
|
|
u32 pitch = 0;
|
|
|
|
u32 width = 0;
|
|
|
|
u32 height = 0;
|
2022-03-21 10:08:23 +00:00
|
|
|
u16* soundbuf = alloc_invisible<u16>(1024 * 2);
|
|
|
|
u32 nsamps = 0;
|
|
|
|
bool hack = false;
|
2022-02-12 02:22:16 +00:00
|
|
|
void (*inputcb)() = nullptr;
|
|
|
|
bool lagged = true;
|
2022-04-15 05:45:10 +00:00
|
|
|
void (*tracecb)(const char*) = nullptr;
|
2022-02-12 02:22:16 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
auto BizPlatform::attach(ares::Node::Object node) -> void
|
|
|
|
{
|
|
|
|
if (auto stream = node->cast<ares::Node::Audio::Stream>())
|
|
|
|
{
|
|
|
|
stream->setResamplerFrequency(44100);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
auto BizPlatform::pak(ares::Node::Object) -> ares::VFS::Pak
|
|
|
|
{
|
|
|
|
return bizpak;
|
|
|
|
}
|
|
|
|
|
2022-04-15 05:45:10 +00:00
|
|
|
auto BizPlatform::log(string_view message) -> void
|
|
|
|
{
|
|
|
|
if (tracecb) tracecb(message.data());
|
|
|
|
}
|
|
|
|
|
2022-02-12 02:22:16 +00:00
|
|
|
auto BizPlatform::video(ares::Node::Video::Screen screen, const u32* data, u32 pitch, u32 width, u32 height) -> void
|
|
|
|
{
|
|
|
|
videobuf = (u32*)data;
|
|
|
|
this->pitch = pitch >> 2;
|
|
|
|
this->width = width;
|
|
|
|
this->height = height;
|
2022-03-21 10:08:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
auto BizPlatform::audio(ares::Node::Audio::Stream stream) -> void
|
|
|
|
{
|
|
|
|
while (stream->pending())
|
|
|
|
{
|
|
|
|
f64 buf[2];
|
|
|
|
stream->read(buf);
|
|
|
|
soundbuf[nsamps * 2 + 0] = (s16)std::clamp(buf[0] * 32768, -32768.0, 32767.0);
|
|
|
|
soundbuf[nsamps * 2 + 1] = (s16)std::clamp(buf[1] * 32768, -32768.0, 32767.0);
|
|
|
|
if (!hack) nsamps++;
|
|
|
|
}
|
2022-02-12 02:22:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
auto BizPlatform::input(ares::Node::Input::Input node) -> void
|
|
|
|
{
|
|
|
|
if (auto input = node->cast<ares::Node::Input::Button>())
|
|
|
|
{
|
2022-03-21 10:08:23 +00:00
|
|
|
if (input->name() == "Start" || input->name() == "Left Click")
|
2022-02-12 02:22:16 +00:00
|
|
|
{
|
|
|
|
lagged = false;
|
|
|
|
if (inputcb) inputcb();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2022-02-16 10:15:27 +00:00
|
|
|
static ares::Node::System root = nullptr;
|
|
|
|
static BizPlatform* platform = nullptr;
|
|
|
|
static array_view<u8>* pifData = nullptr;
|
|
|
|
static array_view<u8>* romData = nullptr;
|
|
|
|
static array_view<u8>* saveData = nullptr;
|
2022-03-21 10:08:23 +00:00
|
|
|
static array_view<u8>* gbRomData[4] = { nullptr, nullptr, nullptr, nullptr, };
|
2022-02-12 02:22:16 +00:00
|
|
|
|
|
|
|
static inline void HackeryDoo()
|
|
|
|
{
|
2022-03-21 10:08:23 +00:00
|
|
|
platform->hack = true;
|
2022-02-12 02:22:16 +00:00
|
|
|
root->run();
|
|
|
|
root->run();
|
2022-03-21 10:08:23 +00:00
|
|
|
platform->hack = false;
|
2022-02-12 02:22:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
typedef enum
|
|
|
|
{
|
|
|
|
NONE,
|
|
|
|
EEPROM512,
|
|
|
|
EEPROM2KB,
|
|
|
|
SRAM32KB,
|
|
|
|
SRAM96KB,
|
2022-03-21 10:08:23 +00:00
|
|
|
SRAM128KB,
|
2022-02-12 02:22:16 +00:00
|
|
|
FLASH128KB,
|
|
|
|
} SaveType;
|
|
|
|
|
|
|
|
static inline SaveType DetectSaveType(u8* rom)
|
|
|
|
{
|
|
|
|
string id;
|
|
|
|
id.append((char)rom[0x3B]);
|
|
|
|
id.append((char)rom[0x3C]);
|
|
|
|
id.append((char)rom[0x3D]);
|
|
|
|
|
|
|
|
char region_code = rom[0x3E];
|
|
|
|
u8 revision = rom[0x3F];
|
|
|
|
|
|
|
|
SaveType ret = NONE;
|
|
|
|
if (id == "NTW") ret = EEPROM512;
|
|
|
|
if (id == "NHF") ret = EEPROM512;
|
|
|
|
if (id == "NOS") ret = EEPROM512;
|
|
|
|
if (id == "NTC") ret = EEPROM512;
|
|
|
|
if (id == "NER") ret = EEPROM512;
|
|
|
|
if (id == "NAG") ret = EEPROM512;
|
|
|
|
if (id == "NAB") ret = EEPROM512;
|
|
|
|
if (id == "NS3") ret = EEPROM512;
|
|
|
|
if (id == "NTN") ret = EEPROM512;
|
|
|
|
if (id == "NBN") ret = EEPROM512;
|
|
|
|
if (id == "NBK") ret = EEPROM512;
|
|
|
|
if (id == "NFH") ret = EEPROM512;
|
|
|
|
if (id == "NMU") ret = EEPROM512;
|
|
|
|
if (id == "NBC") ret = EEPROM512;
|
|
|
|
if (id == "NBH") ret = EEPROM512;
|
|
|
|
if (id == "NHA") ret = EEPROM512;
|
|
|
|
if (id == "NBM") ret = EEPROM512;
|
|
|
|
if (id == "NBV") ret = EEPROM512;
|
|
|
|
if (id == "NBD") ret = EEPROM512;
|
|
|
|
if (id == "NCT") ret = EEPROM512;
|
|
|
|
if (id == "NCH") ret = EEPROM512;
|
|
|
|
if (id == "NCG") ret = EEPROM512;
|
|
|
|
if (id == "NP2") ret = EEPROM512;
|
|
|
|
if (id == "NXO") ret = EEPROM512;
|
|
|
|
if (id == "NCU") ret = EEPROM512;
|
|
|
|
if (id == "NCX") ret = EEPROM512;
|
|
|
|
if (id == "NDY") ret = EEPROM512;
|
|
|
|
if (id == "NDQ") ret = EEPROM512;
|
|
|
|
if (id == "NDR") ret = EEPROM512;
|
|
|
|
if (id == "NN6") ret = EEPROM512;
|
|
|
|
if (id == "NDU") ret = EEPROM512;
|
|
|
|
if (id == "NJM") ret = EEPROM512;
|
|
|
|
if (id == "NFW") ret = EEPROM512;
|
|
|
|
if (id == "NF2") ret = EEPROM512;
|
|
|
|
if (id == "NKA") ret = EEPROM512;
|
|
|
|
if (id == "NFG") ret = EEPROM512;
|
|
|
|
if (id == "NGL") ret = EEPROM512;
|
|
|
|
if (id == "NGV") ret = EEPROM512;
|
|
|
|
if (id == "NGE") ret = EEPROM512;
|
|
|
|
if (id == "NHP") ret = EEPROM512;
|
|
|
|
if (id == "NPG") ret = EEPROM512;
|
|
|
|
if (id == "NIJ") ret = EEPROM512;
|
|
|
|
if (id == "NIC") ret = EEPROM512;
|
|
|
|
if (id == "NFY") ret = EEPROM512;
|
|
|
|
if (id == "NKI") ret = EEPROM512;
|
|
|
|
if (id == "NLL") ret = EEPROM512;
|
|
|
|
if (id == "NLR") ret = EEPROM512;
|
|
|
|
if (id == "NKT") ret = EEPROM512;
|
|
|
|
if (id == "CLB") ret = EEPROM512;
|
|
|
|
if (id == "NLB") ret = EEPROM512;
|
|
|
|
if (id == "NMW") ret = EEPROM512;
|
|
|
|
if (id == "NML") ret = EEPROM512;
|
|
|
|
if (id == "NTM") ret = EEPROM512;
|
|
|
|
if (id == "NMI") ret = EEPROM512;
|
|
|
|
if (id == "NMG") ret = EEPROM512;
|
|
|
|
if (id == "NMO") ret = EEPROM512;
|
|
|
|
if (id == "NMS") ret = EEPROM512;
|
|
|
|
if (id == "NMR") ret = EEPROM512;
|
|
|
|
if (id == "NCR") ret = EEPROM512;
|
|
|
|
if (id == "NEA") ret = EEPROM512;
|
|
|
|
if (id == "NPW") ret = EEPROM512;
|
|
|
|
if (id == "NPM") ret = EEPROM512;
|
|
|
|
if (id == "NPY") ret = EEPROM512;
|
|
|
|
if (id == "NPT") ret = EEPROM512;
|
|
|
|
if (id == "NRA") ret = EEPROM512;
|
|
|
|
if (id == "NWQ") ret = EEPROM512;
|
|
|
|
if (id == "NSU") ret = EEPROM512;
|
|
|
|
if (id == "NSN") ret = EEPROM512;
|
|
|
|
if (id == "NK2") ret = EEPROM512;
|
|
|
|
if (id == "NSV") ret = EEPROM512;
|
|
|
|
if (id == "NFX") ret = EEPROM512;
|
|
|
|
if (id == "NFP") ret = EEPROM512;
|
|
|
|
if (id == "NS6") ret = EEPROM512;
|
|
|
|
if (id == "NNA") ret = EEPROM512;
|
|
|
|
if (id == "NRS") ret = EEPROM512;
|
|
|
|
if (id == "NSW") ret = EEPROM512;
|
|
|
|
if (id == "NSC") ret = EEPROM512;
|
|
|
|
if (id == "NSA") ret = EEPROM512;
|
|
|
|
if (id == "NB6") ret = EEPROM512;
|
|
|
|
if (id == "NSM") ret = EEPROM512;
|
|
|
|
if (id == "NSS") ret = EEPROM512;
|
|
|
|
if (id == "NTX") ret = EEPROM512;
|
|
|
|
if (id == "NT6") ret = EEPROM512;
|
|
|
|
if (id == "NTP") ret = EEPROM512;
|
|
|
|
if (id == "NTJ") ret = EEPROM512;
|
|
|
|
if (id == "NRC") ret = EEPROM512;
|
|
|
|
if (id == "NTR") ret = EEPROM512;
|
|
|
|
if (id == "NTB") ret = EEPROM512;
|
|
|
|
if (id == "NGU") ret = EEPROM512;
|
|
|
|
if (id == "NIR") ret = EEPROM512;
|
|
|
|
if (id == "NVL") ret = EEPROM512;
|
|
|
|
if (id == "NVY") ret = EEPROM512;
|
|
|
|
if (id == "NWR") ret = EEPROM512;
|
|
|
|
if (id == "NWC") ret = EEPROM512;
|
|
|
|
if (id == "NAD") ret = EEPROM512;
|
|
|
|
if (id == "NWU") ret = EEPROM512;
|
|
|
|
if (id == "NYK") ret = EEPROM512;
|
|
|
|
if (id == "NMZ") ret = EEPROM512;
|
|
|
|
if (id == "NDK" && region_code == 'J') ret = EEPROM512;
|
|
|
|
if (id == "NWT" && region_code == 'J') ret = EEPROM512;
|
|
|
|
|
|
|
|
if (id == "NB7") ret = EEPROM2KB;
|
|
|
|
if (id == "NGT") ret = EEPROM2KB;
|
|
|
|
if (id == "NFU") ret = EEPROM2KB;
|
|
|
|
if (id == "NCW") ret = EEPROM2KB;
|
|
|
|
if (id == "NCZ") ret = EEPROM2KB;
|
|
|
|
if (id == "ND6") ret = EEPROM2KB;
|
|
|
|
if (id == "NDO") ret = EEPROM2KB;
|
|
|
|
if (id == "ND2") ret = EEPROM2KB;
|
|
|
|
if (id == "N3D") ret = EEPROM2KB;
|
|
|
|
if (id == "NMX") ret = EEPROM2KB;
|
|
|
|
if (id == "NGC") ret = EEPROM2KB;
|
|
|
|
if (id == "NIM") ret = EEPROM2KB;
|
|
|
|
if (id == "NK4") ret = EEPROM2KB;
|
|
|
|
if (id == "NNB") ret = EEPROM2KB;
|
|
|
|
if (id == "NMV") ret = EEPROM2KB;
|
|
|
|
if (id == "NM8") ret = EEPROM2KB;
|
|
|
|
if (id == "NEV") ret = EEPROM2KB;
|
|
|
|
if (id == "NPP") ret = EEPROM2KB;
|
|
|
|
if (id == "NUB") ret = EEPROM2KB;
|
|
|
|
if (id == "NPD") ret = EEPROM2KB;
|
|
|
|
if (id == "NRZ") ret = EEPROM2KB;
|
|
|
|
if (id == "NR7") ret = EEPROM2KB;
|
|
|
|
if (id == "NEP") ret = EEPROM2KB;
|
|
|
|
if (id == "NYS") ret = EEPROM2KB;
|
|
|
|
if (id == "ND3" && region_code == 'J') ret = EEPROM2KB;
|
|
|
|
if (id == "ND4" && region_code == 'J') ret = EEPROM2KB;
|
|
|
|
|
|
|
|
if (id == "NTE") ret = SRAM32KB;
|
|
|
|
if (id == "NVB") ret = SRAM32KB;
|
|
|
|
if (id == "CFZ") ret = SRAM32KB;
|
|
|
|
if (id == "NFZ") ret = SRAM32KB;
|
|
|
|
if (id == "NSI") ret = SRAM32KB;
|
|
|
|
if (id == "NG6") ret = SRAM32KB;
|
|
|
|
if (id == "N3H") ret = SRAM32KB;
|
|
|
|
if (id == "NGP") ret = SRAM32KB;
|
|
|
|
if (id == "NYW") ret = SRAM32KB;
|
|
|
|
if (id == "NHY") ret = SRAM32KB;
|
|
|
|
if (id == "NIB") ret = SRAM32KB;
|
|
|
|
if (id == "NPS") ret = SRAM32KB;
|
|
|
|
if (id == "NPA") ret = SRAM32KB;
|
|
|
|
if (id == "NP4") ret = SRAM32KB;
|
|
|
|
if (id == "NJ5") ret = SRAM32KB;
|
|
|
|
if (id == "NP6") ret = SRAM32KB;
|
|
|
|
if (id == "NPE") ret = SRAM32KB;
|
|
|
|
if (id == "NJG") ret = SRAM32KB;
|
|
|
|
if (id == "CZL") ret = SRAM32KB;
|
|
|
|
if (id == "NZL") ret = SRAM32KB;
|
|
|
|
if (id == "NKG") ret = SRAM32KB;
|
|
|
|
if (id == "NMF") ret = SRAM32KB;
|
|
|
|
if (id == "NRI") ret = SRAM32KB;
|
|
|
|
if (id == "NUT") ret = SRAM32KB;
|
|
|
|
if (id == "NUM") ret = SRAM32KB;
|
|
|
|
if (id == "NOB") ret = SRAM32KB;
|
|
|
|
if (id == "CPS") ret = SRAM32KB;
|
|
|
|
if (id == "NB5") ret = SRAM32KB;
|
|
|
|
if (id == "NRE") ret = SRAM32KB;
|
|
|
|
if (id == "NAL") ret = SRAM32KB;
|
|
|
|
if (id == "NT3") ret = SRAM32KB;
|
|
|
|
if (id == "NS4") ret = SRAM32KB;
|
|
|
|
if (id == "NA2") ret = SRAM32KB;
|
|
|
|
if (id == "NVP") ret = SRAM32KB;
|
|
|
|
if (id == "NWL") ret = SRAM32KB;
|
|
|
|
if (id == "NW2") ret = SRAM32KB;
|
|
|
|
if (id == "NWX") ret = SRAM32KB;
|
|
|
|
if (id == "NK4" && region_code == 'J' && revision < 2) ret = SRAM32KB;
|
|
|
|
|
|
|
|
if (id == "CDZ") ret = SRAM96KB;
|
|
|
|
|
|
|
|
if (id == "NCC") ret = FLASH128KB;
|
|
|
|
if (id == "NDA") ret = FLASH128KB;
|
|
|
|
if (id == "NAF") ret = FLASH128KB;
|
|
|
|
if (id == "NJF") ret = FLASH128KB;
|
|
|
|
if (id == "NKJ") ret = FLASH128KB;
|
|
|
|
if (id == "NZS") ret = FLASH128KB;
|
|
|
|
if (id == "NM6") ret = FLASH128KB;
|
|
|
|
if (id == "NCK") ret = FLASH128KB;
|
|
|
|
if (id == "NMQ") ret = FLASH128KB;
|
|
|
|
if (id == "NPN") ret = FLASH128KB;
|
|
|
|
if (id == "NPF") ret = FLASH128KB;
|
|
|
|
if (id == "NPO") ret = FLASH128KB;
|
|
|
|
if (id == "CP2") ret = FLASH128KB;
|
|
|
|
if (id == "NP3") ret = FLASH128KB;
|
|
|
|
if (id == "NRH") ret = FLASH128KB;
|
|
|
|
if (id == "NSQ") ret = FLASH128KB;
|
|
|
|
if (id == "NT9") ret = FLASH128KB;
|
|
|
|
if (id == "NW4") ret = FLASH128KB;
|
|
|
|
if (id == "NDP") ret = FLASH128KB;
|
|
|
|
|
2022-03-21 10:08:23 +00:00
|
|
|
if(id[1] == 'E' && id[2] == 'D') {
|
|
|
|
n8 config = revision;
|
|
|
|
if (config.bit(4,7) == 1) ret = EEPROM512;
|
|
|
|
else if (config.bit(4,7) == 2) ret = EEPROM2KB;
|
|
|
|
else if (config.bit(4,7) == 3) ret = SRAM32KB;
|
|
|
|
else if (config.bit(4,7) == 4) ret = SRAM96KB;
|
|
|
|
else if (config.bit(4,7) == 5) ret = FLASH128KB;
|
|
|
|
else if (config.bit(4,7) == 6) ret = SRAM128KB;
|
|
|
|
}
|
|
|
|
|
2022-02-12 02:22:16 +00:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2022-03-12 03:36:56 +00:00
|
|
|
namespace ares::Nintendo64 { extern bool RestrictAnalogRange; extern bool BobDeinterlace; }
|
2022-02-16 10:15:27 +00:00
|
|
|
|
2022-03-21 10:08:23 +00:00
|
|
|
typedef struct
|
|
|
|
{
|
|
|
|
u8* GbRomData;
|
|
|
|
u32 GbRomLen;
|
|
|
|
} GbRom;
|
|
|
|
|
2022-02-16 10:15:27 +00:00
|
|
|
typedef struct
|
|
|
|
{
|
|
|
|
u8* PifData;
|
|
|
|
u32 PifLen;
|
|
|
|
u8* RomData;
|
|
|
|
u32 RomLen;
|
2022-03-21 10:08:23 +00:00
|
|
|
GbRom GbRoms[4];
|
2022-02-16 10:15:27 +00:00
|
|
|
} LoadData;
|
|
|
|
|
|
|
|
typedef enum
|
|
|
|
{
|
|
|
|
RESTRICT_ANALOG_RANGE = 1 << 0,
|
|
|
|
IS_PAL = 1 << 1,
|
2022-03-12 03:36:56 +00:00
|
|
|
BOB_DEINTERLACE = 1 << 2, // weave otherwise (todo: implement this)
|
2022-02-16 10:15:27 +00:00
|
|
|
} LoadFlags;
|
|
|
|
|
2022-03-21 10:08:23 +00:00
|
|
|
#define SET_RTC_CALLBACK(NUM) do { \
|
|
|
|
if (auto pad = dynamic_cast<ares::Nintendo64::Gamepad*>(ares::Nintendo64::controllerPort##NUM.device.data())) \
|
|
|
|
{ \
|
|
|
|
if (auto mbc3 = dynamic_cast<ares::Nintendo64::Mbc3*>(pad->transferPak.mbc.data())) \
|
|
|
|
{ \
|
|
|
|
mbc3->rtcCallback = GetBizTime; \
|
|
|
|
} \
|
|
|
|
} \
|
|
|
|
} while (0)
|
|
|
|
|
2022-02-16 10:15:27 +00:00
|
|
|
EXPORT bool Init(LoadData* loadData, ControllerType* controllers, LoadFlags loadFlags)
|
2022-02-12 02:22:16 +00:00
|
|
|
{
|
2022-02-16 10:15:27 +00:00
|
|
|
platform = new BizPlatform;
|
|
|
|
platform->bizpak = new vfs::directory;
|
|
|
|
|
|
|
|
u8* data;
|
2022-02-12 02:22:16 +00:00
|
|
|
u32 len;
|
|
|
|
string name;
|
|
|
|
|
2022-02-16 10:15:27 +00:00
|
|
|
bool pal = loadFlags & IS_PAL;
|
|
|
|
|
2022-02-12 02:22:16 +00:00
|
|
|
name = pal ? "pif.pal.rom" : "pif.ntsc.rom";
|
2022-02-16 10:15:27 +00:00
|
|
|
len = loadData->PifLen;
|
|
|
|
data = new u8[len];
|
|
|
|
memcpy(data, loadData->PifData, len);
|
|
|
|
pifData = new array_view<u8>(data, len);
|
|
|
|
platform->bizpak->append(name, *pifData);
|
2022-02-12 02:22:16 +00:00
|
|
|
|
|
|
|
name = "program.rom";
|
2022-02-16 10:15:27 +00:00
|
|
|
len = loadData->RomLen;
|
|
|
|
data = new u8[len];
|
|
|
|
memcpy(data, loadData->RomData, len);
|
|
|
|
romData = new array_view<u8>(data, len);
|
|
|
|
platform->bizpak->append(name, *romData);
|
2022-02-12 02:22:16 +00:00
|
|
|
|
|
|
|
string region = pal ? "PAL" : "NTSC";
|
2022-02-16 10:15:27 +00:00
|
|
|
platform->bizpak->setAttribute("region", region);
|
2022-02-12 02:22:16 +00:00
|
|
|
|
|
|
|
string cic = pal ? "CIC-NUS-7101" : "CIC-NUS-6102";
|
2022-02-16 10:15:27 +00:00
|
|
|
u32 crc32 = Hash::CRC32({&data[0x40], 0x9C0}).value();
|
2022-02-12 02:22:16 +00:00
|
|
|
if (crc32 == 0x1DEB51A9) cic = pal ? "CIC-NUS-7102" : "CIC-NUS-6101";
|
|
|
|
if (crc32 == 0xC08E5BD6) cic = pal ? "CIC-NUS-7101" : "CIC-NUS-6102";
|
|
|
|
if (crc32 == 0x03B8376A) cic = pal ? "CIC-NUS-7103" : "CIC-NUS-6103";
|
|
|
|
if (crc32 == 0xCF7F41DC) cic = pal ? "CIC-NUS-7105" : "CIC-NUS-6105";
|
|
|
|
if (crc32 == 0xD1059C6A) cic = pal ? "CIC-NUS-7106" : "CIC-NUS-6106";
|
2022-02-16 10:15:27 +00:00
|
|
|
platform->bizpak->setAttribute("cic", cic);
|
2022-02-12 02:22:16 +00:00
|
|
|
|
2022-02-16 10:15:27 +00:00
|
|
|
SaveType save = DetectSaveType(data);
|
2022-02-12 02:22:16 +00:00
|
|
|
if (save != NONE)
|
|
|
|
{
|
|
|
|
switch (save)
|
|
|
|
{
|
|
|
|
case EEPROM512: len = 512; name = "save.eeprom"; break;
|
|
|
|
case EEPROM2KB: len = 2 * 1024; name = "save.eeprom"; break;
|
|
|
|
case SRAM32KB: len = 32 * 1024; name = "save.ram"; break;
|
|
|
|
case SRAM96KB: len = 96 * 1024; name = "save.ram"; break;
|
2022-03-21 10:08:23 +00:00
|
|
|
case SRAM128KB: len = 128 * 1024; name = "save.ram"; break;
|
2022-02-12 02:22:16 +00:00
|
|
|
case FLASH128KB: len = 128 * 1024; name = "save.flash"; break;
|
2022-03-12 03:36:56 +00:00
|
|
|
default: return false;
|
2022-02-12 02:22:16 +00:00
|
|
|
}
|
2022-02-16 10:15:27 +00:00
|
|
|
data = new u8[len];
|
|
|
|
memset(data, 0xFF, len);
|
|
|
|
saveData = new array_view<u8>(data, len);
|
|
|
|
platform->bizpak->append(name, *saveData);
|
2022-02-12 02:22:16 +00:00
|
|
|
}
|
|
|
|
|
2022-03-21 10:08:23 +00:00
|
|
|
for (int i = 0; i < 4; i++)
|
|
|
|
{
|
|
|
|
if (loadData->GbRoms[i].GbRomData)
|
|
|
|
{
|
|
|
|
len = loadData->GbRoms[i].GbRomLen;
|
|
|
|
data = new u8[len];
|
|
|
|
memcpy(data, loadData->GbRoms[i].GbRomData, len);
|
|
|
|
gbRomData[i] = new array_view<u8>(data, len);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-02-16 10:15:27 +00:00
|
|
|
ares::platform = platform;
|
|
|
|
|
2022-02-12 02:22:16 +00:00
|
|
|
if (!ares::Nintendo64::load(root, {"[Nintendo] Nintendo 64 (", region, ")"}))
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (auto port = root->find<ares::Node::Port>("Cartridge Slot"))
|
|
|
|
{
|
|
|
|
port->allocate();
|
|
|
|
port->connect();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2022-03-21 10:08:23 +00:00
|
|
|
for (int i = 0, j = 0; i < 4; i++)
|
2022-02-12 02:22:16 +00:00
|
|
|
{
|
|
|
|
if (auto port = root->find<ares::Node::Port>({"Controller Port ", 1 + i}))
|
|
|
|
{
|
|
|
|
if (controllers[i] == Unplugged) continue;
|
|
|
|
|
2022-03-21 10:08:23 +00:00
|
|
|
if (controllers[i] == Mouse)
|
|
|
|
{
|
|
|
|
port->allocate("Mouse");
|
|
|
|
port->connect();
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (controllers[i] == Transferpak)
|
|
|
|
{
|
|
|
|
if (gbRomData[j])
|
|
|
|
{
|
|
|
|
platform->bizpak->remove("gbrom.pak");
|
|
|
|
platform->bizpak->append("gbrom.pak", *gbRomData[j++]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-02-12 02:22:16 +00:00
|
|
|
auto peripheral = port->allocate("Gamepad");
|
|
|
|
port->connect();
|
|
|
|
|
|
|
|
switch (controllers[i])
|
|
|
|
{
|
|
|
|
case Mempak: name = "Controller Pak"; break;
|
|
|
|
case Rumblepak: name = "Rumble Pak"; break;
|
2022-03-21 10:08:23 +00:00
|
|
|
case Transferpak: name = "Transfer Pak"; break;
|
2022-02-12 02:22:16 +00:00
|
|
|
default: continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (auto port = peripheral->find<ares::Node::Port>("Pak"))
|
|
|
|
{
|
|
|
|
port->allocate(name);
|
|
|
|
port->connect();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-03-21 10:08:23 +00:00
|
|
|
SET_RTC_CALLBACK(1);
|
|
|
|
SET_RTC_CALLBACK(2);
|
|
|
|
SET_RTC_CALLBACK(3);
|
|
|
|
SET_RTC_CALLBACK(4);
|
|
|
|
|
2022-02-16 10:15:27 +00:00
|
|
|
ares::Nintendo64::RestrictAnalogRange = loadFlags & RESTRICT_ANALOG_RANGE;
|
2022-03-12 03:36:56 +00:00
|
|
|
ares::Nintendo64::BobDeinterlace = loadFlags & BOB_DEINTERLACE;
|
2022-02-13 10:45:48 +00:00
|
|
|
|
2022-02-12 02:22:16 +00:00
|
|
|
root->power(false);
|
|
|
|
HackeryDoo();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2022-03-21 10:08:23 +00:00
|
|
|
// todo: might need to account for mbc5 rumble?
|
|
|
|
// largely pointless tho
|
2022-02-12 02:22:16 +00:00
|
|
|
EXPORT bool GetRumbleStatus(u32 num)
|
|
|
|
{
|
|
|
|
ares::Nintendo64::Gamepad* c = nullptr;
|
|
|
|
switch (num)
|
|
|
|
{
|
2022-03-21 10:08:23 +00:00
|
|
|
case 0: c = dynamic_cast<ares::Nintendo64::Gamepad*>(ares::Nintendo64::controllerPort1.device.data()); break;
|
|
|
|
case 1: c = dynamic_cast<ares::Nintendo64::Gamepad*>(ares::Nintendo64::controllerPort2.device.data()); break;
|
|
|
|
case 2: c = dynamic_cast<ares::Nintendo64::Gamepad*>(ares::Nintendo64::controllerPort3.device.data()); break;
|
|
|
|
case 3: c = dynamic_cast<ares::Nintendo64::Gamepad*>(ares::Nintendo64::controllerPort4.device.data()); break;
|
2022-02-12 02:22:16 +00:00
|
|
|
}
|
|
|
|
return c ? c->motor->enable() : false;
|
|
|
|
}
|
|
|
|
|
2022-02-17 10:48:40 +00:00
|
|
|
#define ADD_MEMORY_DOMAIN(mem, name, flags) do { \
|
|
|
|
m[i].Data = ares::Nintendo64::mem.data; \
|
|
|
|
m[i].Name = name; \
|
|
|
|
m[i].Size = ares::Nintendo64::mem.size; \
|
|
|
|
m[i].Flags = flags | MEMORYAREA_FLAGS_YUGEENDIAN | MEMORYAREA_FLAGS_SWAPPED | MEMORYAREA_FLAGS_WORDSIZE4 | MEMORYAREA_FLAGS_WRITABLE; \
|
|
|
|
i++; \
|
2022-03-21 10:08:23 +00:00
|
|
|
} while (0)
|
2022-02-12 02:22:16 +00:00
|
|
|
|
2022-03-21 10:08:23 +00:00
|
|
|
#define ADD_MEMPAK_DOMAIN(NUM) do { \
|
|
|
|
if (auto c = dynamic_cast<ares::Nintendo64::Gamepad*>(ares::Nintendo64::controllerPort##NUM.device.data())) \
|
2022-02-12 02:22:16 +00:00
|
|
|
{ \
|
2022-02-17 10:48:40 +00:00
|
|
|
m[i].Data = c->ram.data; \
|
2022-03-21 10:08:23 +00:00
|
|
|
m[i].Name = "MEMPAK " #NUM; \
|
2022-02-17 10:48:40 +00:00
|
|
|
m[i].Size = c->ram.size; \
|
|
|
|
m[i].Flags = MEMORYAREA_FLAGS_ONEFILLED | MEMORYAREA_FLAGS_SAVERAMMABLE | MEMORYAREA_FLAGS_YUGEENDIAN | MEMORYAREA_FLAGS_SWAPPED | MEMORYAREA_FLAGS_WORDSIZE4 | MEMORYAREA_FLAGS_WRITABLE; \
|
|
|
|
i++; \
|
2022-02-12 02:22:16 +00:00
|
|
|
} \
|
2022-03-21 10:08:23 +00:00
|
|
|
} while (0)
|
|
|
|
|
|
|
|
#define ADD_GB_DOMAINS(NUM) do { \
|
|
|
|
if (auto c = dynamic_cast<ares::Nintendo64::Gamepad*>(ares::Nintendo64::controllerPort##NUM.device.data())) \
|
|
|
|
{ \
|
|
|
|
m[i].Data = c->transferPak.rom.data; \
|
|
|
|
m[i].Name = "GB ROM " #NUM; \
|
|
|
|
m[i].Size = c->transferPak.rom.size; \
|
2022-04-15 05:45:10 +00:00
|
|
|
m[i].Flags = MEMORYAREA_FLAGS_YUGEENDIAN | MEMORYAREA_FLAGS_SWAPPED | MEMORYAREA_FLAGS_WORDSIZE4 | MEMORYAREA_FLAGS_WRITABLE; \
|
2022-03-21 10:08:23 +00:00
|
|
|
i++; \
|
|
|
|
\
|
|
|
|
m[i].Data = c->transferPak.ram.data; \
|
|
|
|
m[i].Name = "GB SRAM " #NUM; \
|
|
|
|
m[i].Size = c->transferPak.ram.size; \
|
2022-04-15 05:45:10 +00:00
|
|
|
m[i].Flags = MEMORYAREA_FLAGS_ONEFILLED | MEMORYAREA_FLAGS_SAVERAMMABLE | MEMORYAREA_FLAGS_YUGEENDIAN | MEMORYAREA_FLAGS_SWAPPED | MEMORYAREA_FLAGS_WORDSIZE4 | MEMORYAREA_FLAGS_WRITABLE; \
|
2022-03-21 10:08:23 +00:00
|
|
|
i++; \
|
|
|
|
} \
|
|
|
|
} while (0)
|
2022-02-12 02:22:16 +00:00
|
|
|
|
2022-04-15 05:45:10 +00:00
|
|
|
static inline u8 GetByteFromWord(u32 word, u32 addr)
|
|
|
|
{
|
|
|
|
switch (addr & 3)
|
|
|
|
{
|
|
|
|
case 0: return (word >> 24) & 0xFF;
|
|
|
|
case 1: return (word >> 16) & 0xFF;
|
|
|
|
case 2: return (word >> 8) & 0xFF;
|
|
|
|
case 3: return (word >> 0) & 0xFF;
|
|
|
|
default: __builtin_unreachable();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static u8 PeekFunc(u64 address)
|
|
|
|
{
|
|
|
|
address &= 0x1fff'ffff;
|
|
|
|
const u32 addr = address;
|
|
|
|
|
|
|
|
if (addr > 0x0403'ffff && addr <= 0x0407'ffff) // RSP
|
|
|
|
{
|
|
|
|
address = (address & 0x3ffff) >> 2;
|
|
|
|
if (address == 7) // SP_SEMAPHORE
|
|
|
|
{
|
|
|
|
return GetByteFromWord(ares::Nintendo64::rsp.status.semaphore & 1, addr);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (addr > 0x0407'ffff && addr <= 0x040f'ffff) // RSP Status
|
|
|
|
{
|
|
|
|
address = (address & 0x7ffff) >> 2;
|
|
|
|
if (address == 0) // SP_PC_REG
|
|
|
|
{
|
|
|
|
return GetByteFromWord(ares::Nintendo64::rsp.ipu.pc & 0xFFF, addr);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (addr > 0x046f'ffff && addr <= 0x047f'ffff) // RI
|
|
|
|
{
|
|
|
|
address = (address & 0xfffff) >> 2;
|
|
|
|
if (address == 3) // RI_SELECT
|
|
|
|
{
|
|
|
|
return GetByteFromWord(ares::Nintendo64::ri.io.select, addr);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return ares::Nintendo64::bus.read<ares::Nintendo64::Byte>(addr);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void SysBusAccess(u8* buffer, u64 address, u64 count, bool write)
|
|
|
|
{
|
|
|
|
if (write)
|
|
|
|
{
|
|
|
|
while (count--)
|
|
|
|
ares::Nintendo64::bus.write<ares::Nintendo64::Byte>(address++, *buffer++);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
while (count--)
|
|
|
|
*buffer++ = PeekFunc(address++);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-02-12 02:22:16 +00:00
|
|
|
EXPORT void GetMemoryAreas(MemoryArea *m)
|
|
|
|
{
|
|
|
|
int i = 0;
|
2022-02-17 10:48:40 +00:00
|
|
|
ADD_MEMORY_DOMAIN(rdram.ram, "RDRAM", MEMORYAREA_FLAGS_PRIMARY);
|
|
|
|
ADD_MEMORY_DOMAIN(cartridge.rom, "ROM", 0);
|
2022-05-27 05:26:56 +00:00
|
|
|
ADD_MEMORY_DOMAIN(pif.rom, "PIF ROM", 0);
|
|
|
|
ADD_MEMORY_DOMAIN(pif.ram, "PIF RAM", 0);
|
2022-02-17 10:48:40 +00:00
|
|
|
ADD_MEMORY_DOMAIN(rsp.dmem, "RSP DMEM", 0);
|
|
|
|
ADD_MEMORY_DOMAIN(rsp.imem, "RSP IMEM", 0);
|
|
|
|
ADD_MEMORY_DOMAIN(cartridge.ram, "SRAM", MEMORYAREA_FLAGS_ONEFILLED | MEMORYAREA_FLAGS_SAVERAMMABLE);
|
|
|
|
ADD_MEMORY_DOMAIN(cartridge.eeprom, "EEPROM", MEMORYAREA_FLAGS_ONEFILLED | MEMORYAREA_FLAGS_SAVERAMMABLE);
|
|
|
|
ADD_MEMORY_DOMAIN(cartridge.flash, "FLASH", MEMORYAREA_FLAGS_ONEFILLED | MEMORYAREA_FLAGS_SAVERAMMABLE);
|
|
|
|
ADD_MEMPAK_DOMAIN(1);
|
|
|
|
ADD_MEMPAK_DOMAIN(2);
|
|
|
|
ADD_MEMPAK_DOMAIN(3);
|
|
|
|
ADD_MEMPAK_DOMAIN(4);
|
2022-03-21 10:08:23 +00:00
|
|
|
ADD_GB_DOMAINS(1);
|
|
|
|
ADD_GB_DOMAINS(2);
|
|
|
|
ADD_GB_DOMAINS(3);
|
|
|
|
ADD_GB_DOMAINS(4);
|
2022-04-15 05:45:10 +00:00
|
|
|
|
|
|
|
m[i].Data = (void*)SysBusAccess;
|
|
|
|
m[i].Name = "System Bus";
|
|
|
|
m[i].Size = 1ull << 32;
|
|
|
|
m[i].Flags = MEMORYAREA_FLAGS_YUGEENDIAN | MEMORYAREA_FLAGS_SWAPPED | MEMORYAREA_FLAGS_WORDSIZE4 | MEMORYAREA_FLAGS_WRITABLE | MEMORYAREA_FLAGS_FUNCTIONHOOK;
|
2022-02-12 02:22:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
struct MyFrameInfo : public FrameInfo
|
|
|
|
{
|
2022-03-21 10:08:23 +00:00
|
|
|
u64 Time;
|
|
|
|
|
2022-02-12 02:22:16 +00:00
|
|
|
Buttons_t P1Buttons;
|
|
|
|
Buttons_t P2Buttons;
|
|
|
|
Buttons_t P3Buttons;
|
|
|
|
Buttons_t P4Buttons;
|
|
|
|
|
|
|
|
s16 P1XAxis;
|
|
|
|
s16 P1YAxis;
|
|
|
|
|
|
|
|
s16 P2XAxis;
|
|
|
|
s16 P2YAxis;
|
|
|
|
|
|
|
|
s16 P3XAxis;
|
|
|
|
s16 P3YAxis;
|
|
|
|
|
|
|
|
s16 P4XAxis;
|
|
|
|
s16 P4YAxis;
|
|
|
|
|
|
|
|
bool Reset;
|
|
|
|
bool Power;
|
|
|
|
};
|
|
|
|
|
|
|
|
#define UPDATE_CONTROLLER(NUM) do { \
|
2022-03-21 10:08:23 +00:00
|
|
|
if (auto c = dynamic_cast<ares::Nintendo64::Gamepad*>(ares::Nintendo64::controllerPort##NUM.device.data())) \
|
2022-02-12 02:22:16 +00:00
|
|
|
{ \
|
|
|
|
c->x->setValue(f->P##NUM##XAxis); \
|
|
|
|
c->y->setValue(f->P##NUM##YAxis); \
|
|
|
|
c->up->setValue(f->P##NUM##Buttons & UP); \
|
|
|
|
c->down->setValue(f->P##NUM##Buttons & DOWN); \
|
|
|
|
c->left->setValue(f->P##NUM##Buttons & LEFT); \
|
|
|
|
c->right->setValue(f->P##NUM##Buttons & RIGHT); \
|
|
|
|
c->b->setValue(f->P##NUM##Buttons & B); \
|
|
|
|
c->a->setValue(f->P##NUM##Buttons & A); \
|
|
|
|
c->cameraUp->setValue(f->P##NUM##Buttons & C_UP); \
|
|
|
|
c->cameraDown->setValue(f->P##NUM##Buttons & C_DOWN); \
|
|
|
|
c->cameraLeft->setValue(f->P##NUM##Buttons & C_LEFT); \
|
|
|
|
c->cameraRight->setValue(f->P##NUM##Buttons & C_RIGHT); \
|
|
|
|
c->l->setValue(f->P##NUM##Buttons & L); \
|
|
|
|
c->r->setValue(f->P##NUM##Buttons & R); \
|
|
|
|
c->z->setValue(f->P##NUM##Buttons & Z); \
|
|
|
|
c->start->setValue(f->P##NUM##Buttons & START); \
|
|
|
|
} \
|
2022-03-21 10:08:23 +00:00
|
|
|
else if (auto m = dynamic_cast<ares::Nintendo64::Mouse*>(ares::Nintendo64::controllerPort##NUM.device.data())) \
|
|
|
|
{ \
|
|
|
|
m->x->setValue(f->P##NUM##XAxis); \
|
|
|
|
m->y->setValue(f->P##NUM##YAxis); \
|
|
|
|
m->rclick->setValue(f->P##NUM##Buttons & B); \
|
|
|
|
m->lclick->setValue(f->P##NUM##Buttons & A); \
|
|
|
|
} \
|
2022-02-12 02:22:16 +00:00
|
|
|
} while (0)
|
|
|
|
|
|
|
|
EXPORT void FrameAdvance(MyFrameInfo* f)
|
|
|
|
{
|
|
|
|
if (f->Power)
|
|
|
|
{
|
|
|
|
root->power(false);
|
|
|
|
HackeryDoo();
|
|
|
|
}
|
|
|
|
else if (f->Reset)
|
|
|
|
{
|
|
|
|
root->power(true);
|
|
|
|
HackeryDoo();
|
|
|
|
}
|
|
|
|
|
|
|
|
UPDATE_CONTROLLER(1);
|
|
|
|
UPDATE_CONTROLLER(2);
|
|
|
|
UPDATE_CONTROLLER(3);
|
|
|
|
UPDATE_CONTROLLER(4);
|
|
|
|
|
2022-02-16 10:15:27 +00:00
|
|
|
platform->lagged = true;
|
2022-03-21 10:08:23 +00:00
|
|
|
platform->nsamps = 0;
|
|
|
|
biztime = f->Time;
|
2022-02-12 02:22:16 +00:00
|
|
|
|
|
|
|
root->run();
|
|
|
|
|
2022-02-16 10:15:27 +00:00
|
|
|
f->Width = platform->width;
|
|
|
|
f->Height = platform->height;
|
2022-03-21 10:08:23 +00:00
|
|
|
u32* src = platform->videobuf;
|
|
|
|
u32* dst = f->VideoBuffer;
|
|
|
|
for (int i = 0; i < f->Height; i++)
|
2022-02-12 02:22:16 +00:00
|
|
|
{
|
2022-03-21 10:08:23 +00:00
|
|
|
memcpy(dst, src, f->Width * 4);
|
|
|
|
dst += f->Width;
|
|
|
|
src += platform->pitch;
|
2022-02-12 02:22:16 +00:00
|
|
|
}
|
|
|
|
|
2022-03-21 10:08:23 +00:00
|
|
|
f->Samples = platform->nsamps;
|
|
|
|
memcpy(f->SoundBuffer, platform->soundbuf, f->Samples * 4);
|
2022-02-12 02:22:16 +00:00
|
|
|
|
2022-02-16 10:15:27 +00:00
|
|
|
f->Lagged = platform->lagged;
|
2022-02-12 02:22:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
EXPORT void SetInputCallback(void (*callback)())
|
|
|
|
{
|
2022-02-16 10:15:27 +00:00
|
|
|
platform->inputcb = callback;
|
2022-03-12 03:36:56 +00:00
|
|
|
}
|
2022-04-15 05:45:10 +00:00
|
|
|
|
|
|
|
EXPORT void GetDisassembly(u32 address, u32 instruction, char* buf)
|
|
|
|
{
|
|
|
|
auto s = ares::Nintendo64::cpu.disassembler.disassemble(address, instruction).strip();
|
|
|
|
strcpy(buf, s.data());
|
|
|
|
}
|
|
|
|
|
|
|
|
EXPORT void SetTraceCallback(void (*callback)(const char*))
|
|
|
|
{
|
|
|
|
ares::Nintendo64::cpu.debugger.tracer.instruction->setEnabled(!!callback);
|
|
|
|
platform->tracecb = callback;
|
|
|
|
}
|
|
|
|
|
|
|
|
EXPORT void GetRegisters(u64* buf)
|
|
|
|
{
|
|
|
|
for (int i = 0; i < 32; i++)
|
|
|
|
{
|
|
|
|
buf[i] = ares::Nintendo64::cpu.ipu.r[i].u64;
|
|
|
|
}
|
|
|
|
|
|
|
|
buf[32] = ares::Nintendo64::cpu.ipu.lo.u64;
|
|
|
|
buf[33] = ares::Nintendo64::cpu.ipu.hi.u64;
|
|
|
|
buf[34] = ares::Nintendo64::cpu.ipu.pc;
|
|
|
|
}
|