Fix Windows CI (linux still bork)
Update unarr Add new log options Minor improvements
This commit is contained in:
9
.github/workflows/build.yml
vendored
9
.github/workflows/build.yml
vendored
@@ -9,14 +9,11 @@ jobs:
|
|||||||
submodules: recursive
|
submodules: recursive
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: |
|
run: |
|
||||||
|
sudo add-apt-repository universe
|
||||||
sudo apt-get update -qq
|
sudo apt-get update -qq
|
||||||
sudo apt-get install -y build-essential libgtk-3-dev libsdl2-dev git ninja-build nlohmann-json3-dev
|
sudo apt-get install -y build-essential libgtk-3-dev libsdl2-dev git ninja-build nlohmann-json3-dev libfmt-dev
|
||||||
sudo apt-get install -y vulkan-tools libvulkan1 libvulkan-dev vulkan-validationlayers-dev spirv-tools libsfml-dev
|
sudo apt-get install -y vulkan-tools libvulkan1 libvulkan-dev vulkan-validationlayers-dev spirv-tools libsfml-dev
|
||||||
git clone --recursive https://github.com/fmtlib/fmt
|
|
||||||
cd fmt
|
|
||||||
cmake -B build -DFMT_TEST=OFF
|
|
||||||
cd build
|
|
||||||
sudo make install
|
|
||||||
git clone --recursive https://github.com/mandreyel/mio
|
git clone --recursive https://github.com/mandreyel/mio
|
||||||
cd mio
|
cd mio
|
||||||
cmake -B build -DBUILD_TESTING=False -DCMAKE_BUILD_TYPE=Release
|
cmake -B build -DBUILD_TESTING=False -DCMAKE_BUILD_TYPE=Release
|
||||||
|
|||||||
@@ -55,6 +55,7 @@ endif()
|
|||||||
add_subdirectory(frontend)
|
add_subdirectory(frontend)
|
||||||
add_subdirectory(frontend/imgui)
|
add_subdirectory(frontend/imgui)
|
||||||
add_subdirectory(backend)
|
add_subdirectory(backend)
|
||||||
|
add_subdirectory(backend/netplay)
|
||||||
add_subdirectory(backend/core)
|
add_subdirectory(backend/core)
|
||||||
add_subdirectory(backend/core/interpreter)
|
add_subdirectory(backend/core/interpreter)
|
||||||
add_subdirectory(backend/core/mem)
|
add_subdirectory(backend/core/mem)
|
||||||
|
|||||||
@@ -1,55 +1,8 @@
|
|||||||
#include <Netplay.hpp>
|
#include <Netplay.hpp>
|
||||||
#include "log.hpp"
|
#include <log.hpp>
|
||||||
#include "PIF/Device.hpp"
|
|
||||||
#include <PIF.hpp>
|
#include <PIF.hpp>
|
||||||
#include <array>
|
#include <array>
|
||||||
|
|
||||||
namespace Netplay {
|
namespace Netplay {
|
||||||
bool isHost = false;
|
|
||||||
bool connected = false;
|
bool connected = false;
|
||||||
std::array<std::string, 4> IPs{};
|
|
||||||
|
|
||||||
template <int port>
|
|
||||||
n64::JoybusDevice RequestDataFromRemotePlayer() {
|
|
||||||
sf::UdpSocket sock;
|
|
||||||
u16 remotePort = 53000;
|
|
||||||
sf::IpAddress remoteAddress = IPs[port];
|
|
||||||
if(sock.bind(remotePort) != sf::Socket::Done) {
|
|
||||||
Util::panic("Could not bind UDP connection");
|
|
||||||
}
|
|
||||||
|
|
||||||
sf::Packet res;
|
|
||||||
if(sock.receive(res, remoteAddress, remotePort) != sf::Socket::Done) {
|
|
||||||
Util::panic("Could not receive data from other players");
|
|
||||||
}
|
|
||||||
|
|
||||||
n64::JoybusDevice result{};
|
|
||||||
result << res;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <int port>
|
|
||||||
void SendDataToRemotePlayer() {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
template <int port>
|
|
||||||
void SyncPlayers(n64::PIF& pif) {
|
|
||||||
if(connected) {
|
|
||||||
if(isHost) {
|
|
||||||
pif.PollController();
|
|
||||||
} else {
|
|
||||||
if constexpr (port == 0) {
|
|
||||||
Util::panic("It shouldn't be possible to be player 1 and not be the host");
|
|
||||||
} else {
|
|
||||||
if constexpr (port > 3) {
|
|
||||||
Util::panic("What the heeeeelll oh my gaaaa");
|
|
||||||
}
|
|
||||||
|
|
||||||
n64::players[port] = RequestDataFromRemotePlayer<port>();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template void SyncPlayers(n64::PIF&);
|
|
||||||
}
|
}
|
||||||
@@ -3,9 +3,5 @@
|
|||||||
#include <PIF.hpp>
|
#include <PIF.hpp>
|
||||||
|
|
||||||
namespace Netplay {
|
namespace Netplay {
|
||||||
extern bool isHost;
|
|
||||||
extern bool connected;
|
extern bool connected;
|
||||||
|
|
||||||
template <int port = 0>
|
|
||||||
void SyncPlayers(n64::PIF&);
|
|
||||||
}
|
}
|
||||||
@@ -6,7 +6,7 @@ namespace n64 {
|
|||||||
#define AUDIO_SAMPLE_RATE 44100
|
#define AUDIO_SAMPLE_RATE 44100
|
||||||
#define SYSTEM_SAMPLE_FORMAT AUDIO_F32SYS
|
#define SYSTEM_SAMPLE_FORMAT AUDIO_F32SYS
|
||||||
#define SYSTEM_SAMPLE_SIZE 4
|
#define SYSTEM_SAMPLE_SIZE 4
|
||||||
#define BYTES_PER_HALF_SECOND ((AUDIO_SAMPLE_RATE / 2) * SYSTEM_SAMPLE_SIZE)
|
#define BYTES_PER_HALF_SECOND (((float)AUDIO_SAMPLE_RATE / 2) * SYSTEM_SAMPLE_SIZE)
|
||||||
|
|
||||||
static SDL_AudioStream* audioStream = nullptr;
|
static SDL_AudioStream* audioStream = nullptr;
|
||||||
SDL_mutex* audioStreamMutex;
|
SDL_mutex* audioStreamMutex;
|
||||||
@@ -70,7 +70,7 @@ void PushSample(float left, float volumeL, float right, float volumeR) {
|
|||||||
float adjustedR = right * volumeR;
|
float adjustedR = right * volumeR;
|
||||||
float samples[2]{ adjustedL, adjustedR };
|
float samples[2]{ adjustedL, adjustedR };
|
||||||
|
|
||||||
int availableBytes = SDL_AudioStreamAvailable(audioStream);
|
float availableBytes = SDL_AudioStreamAvailable(audioStream);
|
||||||
if(availableBytes <= BYTES_PER_HALF_SECOND) {
|
if(availableBytes <= BYTES_PER_HALF_SECOND) {
|
||||||
SDL_AudioStreamPut(audioStream, samples, 2 * sizeof(float));
|
SDL_AudioStreamPut(audioStream, samples, 2 * sizeof(float));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,8 +32,6 @@ auto AI::Read(u32 addr) const -> u32 {
|
|||||||
return dmaLen[0];
|
return dmaLen[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
#define max(x, y) ((x) > (y) ? (x) : (y))
|
|
||||||
|
|
||||||
void AI::Write(Mem& mem, Registers& regs, u32 addr, u32 val) {
|
void AI::Write(Mem& mem, Registers& regs, u32 addr, u32 val) {
|
||||||
switch(addr) {
|
switch(addr) {
|
||||||
case 0x04500000:
|
case 0x04500000:
|
||||||
@@ -43,8 +41,8 @@ void AI::Write(Mem& mem, Registers& regs, u32 addr, u32 val) {
|
|||||||
break;
|
break;
|
||||||
case 0x04500004: {
|
case 0x04500004: {
|
||||||
u32 len = (val & 0x3FFFF) & ~7;
|
u32 len = (val & 0x3FFFF) & ~7;
|
||||||
if((dmaCount < 2) && len) {
|
if(dmaCount < 2) {
|
||||||
// if(dmaCount == 0) InterruptRaise(mem.mmio.mi, regs, Interrupt::AI);
|
if(dmaCount == 0) InterruptRaise(mem.mmio.mi, regs, Interrupt::AI);
|
||||||
dmaLen[dmaCount] = len;
|
dmaLen[dmaCount] = len;
|
||||||
dmaCount++;
|
dmaCount++;
|
||||||
}
|
}
|
||||||
@@ -58,7 +56,7 @@ void AI::Write(Mem& mem, Registers& regs, u32 addr, u32 val) {
|
|||||||
case 0x04500010: {
|
case 0x04500010: {
|
||||||
u32 old_dac_freq = dac.freq;
|
u32 old_dac_freq = dac.freq;
|
||||||
dacRate = val & 0x3FFF;
|
dacRate = val & 0x3FFF;
|
||||||
dac.freq = max(1, N64_CPU_FREQ / 2 / (dacRate + 1)) * 1.037;
|
dac.freq = std::max(1u, GetVideoFrequency(mem.IsROMPAL()) / (dacRate + 1));
|
||||||
dac.period = N64_CPU_FREQ / dac.freq;
|
dac.period = N64_CPU_FREQ / dac.freq;
|
||||||
if(old_dac_freq != dac.freq) {
|
if(old_dac_freq != dac.freq) {
|
||||||
AdjustSampleRate(dac.freq);
|
AdjustSampleRate(dac.freq);
|
||||||
|
|||||||
@@ -122,7 +122,7 @@ void PI::Write(Mem& mem, Registers& regs, u32 addr, u32 val) {
|
|||||||
for (int i = 0; i < rdLen; i++) {
|
for (int i = 0; i < rdLen; i++) {
|
||||||
mem.rom.cart[BYTE_ADDRESS(cartAddrInternal + i) & mem.rom.mask] = mem.mmio.rdp.rdram[BYTE_ADDRESS(dramAddrInternal + i) & RDRAM_DSIZE];
|
mem.rom.cart[BYTE_ADDRESS(cartAddrInternal + i) & mem.rom.mask] = mem.mmio.rdp.rdram[BYTE_ADDRESS(dramAddrInternal + i) & RDRAM_DSIZE];
|
||||||
}
|
}
|
||||||
Util::debug("PI DMA from RDRAM to CARTRIDGE (size: {} B, {:08X} to {:08X})", len, dramAddr, cartAddr);
|
Util::trace("PI DMA from RDRAM to CARTRIDGE (size: {} B, {:08X} to {:08X})", len, dramAddr, cartAddr);
|
||||||
dmaBusy = true;
|
dmaBusy = true;
|
||||||
ioBusy = true;
|
ioBusy = true;
|
||||||
scheduler.enqueueRelative(Event{PIAccessTiming(*this, PIGetDomain(cartAddr), len), OnDMAComplete<true>});
|
scheduler.enqueueRelative(Event{PIAccessTiming(*this, PIGetDomain(cartAddr), len), OnDMAComplete<true>});
|
||||||
@@ -140,7 +140,7 @@ void PI::Write(Mem& mem, Registers& regs, u32 addr, u32 val) {
|
|||||||
}
|
}
|
||||||
dmaBusy = true;
|
dmaBusy = true;
|
||||||
ioBusy = true;
|
ioBusy = true;
|
||||||
Util::debug("PI DMA from CARTRIDGE to RDRAM (size: {} B, {:08X} to {:08X})", len, cartAddr, dramAddr);
|
Util::trace("PI DMA from CARTRIDGE to RDRAM (size: {} B, {:08X} to {:08X})", len, cartAddr, dramAddr);
|
||||||
scheduler.enqueueRelative(Event{PIAccessTiming(*this, PIGetDomain(cartAddr), len), OnDMAComplete<false>});
|
scheduler.enqueueRelative(Event{PIAccessTiming(*this, PIGetDomain(cartAddr), len), OnDMAComplete<false>});
|
||||||
} break;
|
} break;
|
||||||
case 0x04600010:
|
case 0x04600010:
|
||||||
|
|||||||
@@ -6,7 +6,6 @@
|
|||||||
#include <cic_nus_6105/n64_cic_nus_6105.hpp>
|
#include <cic_nus_6105/n64_cic_nus_6105.hpp>
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <Netplay.hpp>
|
#include <Netplay.hpp>
|
||||||
#include <PIF/Device.hpp>
|
|
||||||
|
|
||||||
#define MEMPAK_SIZE 32768
|
#define MEMPAK_SIZE 32768
|
||||||
|
|
||||||
@@ -207,10 +206,7 @@ void PIF::ProcessCommands(Mem &mem) {
|
|||||||
break;
|
break;
|
||||||
case 7:
|
case 7:
|
||||||
switch(cmd[CMD_START]) {
|
switch(cmd[CMD_START]) {
|
||||||
case 0: case 3:
|
case 0: case 1: case 3:
|
||||||
for(int i = 0; i < 8; i++) {
|
|
||||||
res[i] = 0;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case 2: {
|
case 2: {
|
||||||
auto now = std::time(nullptr);
|
auto now = std::time(nullptr);
|
||||||
@@ -332,21 +328,11 @@ void PIF::EepromWrite(const u8* cmd, u8* res, const Mem& mem) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void PIF::UpdateController() {
|
void PIF::UpdateController() {
|
||||||
joybusDevices[channel].controller.a = players[channel].controller.a;
|
if(Netplay::connected) {
|
||||||
joybusDevices[channel].controller.b = players[channel].controller.b;
|
Util::panic("Netplay!!!");
|
||||||
joybusDevices[channel].controller.z = players[channel].controller.z;
|
} else {
|
||||||
joybusDevices[channel].controller.start = players[channel].controller.start;
|
PollController();
|
||||||
joybusDevices[channel].controller.dp_up = players[channel].controller.dp_up;
|
}
|
||||||
joybusDevices[channel].controller.dp_down = players[channel].controller.dp_down;
|
|
||||||
joybusDevices[channel].controller.dp_left = players[channel].controller.dp_left;
|
|
||||||
joybusDevices[channel].controller.dp_right = players[channel].controller.dp_right;
|
|
||||||
joybusDevices[channel].controller.joy_reset = players[channel].controller.joy_reset;
|
|
||||||
joybusDevices[channel].controller.l = players[channel].controller.l;
|
|
||||||
joybusDevices[channel].controller.r = players[channel].controller.r;
|
|
||||||
joybusDevices[channel].controller.c_up = players[channel].controller.c_up;
|
|
||||||
joybusDevices[channel].controller.c_down = players[channel].controller.c_down;
|
|
||||||
joybusDevices[channel].controller.c_left = players[channel].controller.c_left;
|
|
||||||
joybusDevices[channel].controller.c_right = players[channel].controller.c_right;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void PIF::DoPIFHLE(Mem& mem, Registers& regs, bool pal, CICType cicType) {
|
void PIF::DoPIFHLE(Mem& mem, Registers& regs, bool pal, CICType cicType) {
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ namespace fs = std::filesystem;
|
|||||||
|
|
||||||
namespace n64 {
|
namespace n64 {
|
||||||
|
|
||||||
enum AccessoryType {
|
enum AccessoryType : u8 {
|
||||||
ACCESSORY_NONE,
|
ACCESSORY_NONE,
|
||||||
ACCESSORY_MEMPACK,
|
ACCESSORY_MEMPACK,
|
||||||
ACCESSORY_RUMBLE_PACK
|
ACCESSORY_RUMBLE_PACK
|
||||||
@@ -18,7 +18,7 @@ enum AccessoryType {
|
|||||||
|
|
||||||
struct Controller {
|
struct Controller {
|
||||||
union {
|
union {
|
||||||
u8 byte1;
|
u8 byte1{};
|
||||||
struct {
|
struct {
|
||||||
bool dp_right:1;
|
bool dp_right:1;
|
||||||
bool dp_left:1;
|
bool dp_left:1;
|
||||||
@@ -31,7 +31,7 @@ struct Controller {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
union {
|
union {
|
||||||
u8 byte2;
|
u8 byte2{};
|
||||||
struct {
|
struct {
|
||||||
bool c_right:1;
|
bool c_right:1;
|
||||||
bool c_left:1;
|
bool c_left:1;
|
||||||
@@ -45,11 +45,21 @@ struct Controller {
|
|||||||
};
|
};
|
||||||
s8 joy_x{};
|
s8 joy_x{};
|
||||||
s8 joy_y{};
|
s8 joy_y{};
|
||||||
|
|
||||||
|
Controller() = default;
|
||||||
|
Controller& operator=(u32 v) {
|
||||||
|
joy_y = v & 0xff;
|
||||||
|
joy_x = v >> 8;
|
||||||
|
byte2 = v >> 16;
|
||||||
|
byte1 = v >> 24;
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
static_assert(sizeof(Controller) == 4);
|
static_assert(sizeof(Controller) == 4);
|
||||||
|
|
||||||
enum JoybusType {
|
enum JoybusType : u8 {
|
||||||
JOYBUS_NONE,
|
JOYBUS_NONE,
|
||||||
JOYBUS_CONTROLLER,
|
JOYBUS_CONTROLLER,
|
||||||
JOYBUS_DANCEPAD,
|
JOYBUS_DANCEPAD,
|
||||||
@@ -66,8 +76,12 @@ struct JoybusDevice {
|
|||||||
AccessoryType accessoryType{};
|
AccessoryType accessoryType{};
|
||||||
Controller controller{};
|
Controller controller{};
|
||||||
|
|
||||||
auto operator<<(const sf::Packet& packet) {
|
JoybusDevice() = default;
|
||||||
|
|
||||||
|
explicit JoybusDevice(const u64& packet) {
|
||||||
|
type = static_cast<JoybusType>(packet >> offsetof(JoybusDevice, type));
|
||||||
|
accessoryType = static_cast<AccessoryType>((packet >> offsetof(JoybusDevice, accessoryType)) & 0xff);
|
||||||
|
controller = packet >> offsetof(JoybusDevice, controller);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -1,13 +1,10 @@
|
|||||||
#include <PIF.hpp>
|
#include <PIF.hpp>
|
||||||
#include <MupenMovie.hpp>
|
#include <MupenMovie.hpp>
|
||||||
#include <PIF/Device.hpp>
|
|
||||||
#include <Netplay.hpp>
|
#include <Netplay.hpp>
|
||||||
#include "log.hpp"
|
#include <log.hpp>
|
||||||
#include <SDL2/SDL_keyboard.h>
|
#include <SDL2/SDL_keyboard.h>
|
||||||
|
|
||||||
namespace n64 {
|
namespace n64 {
|
||||||
JoybusDevice players[4]{};
|
|
||||||
|
|
||||||
void PIF::InitDevices(SaveType saveType) {
|
void PIF::InitDevices(SaveType saveType) {
|
||||||
for (int i = 0; i < 4; i++) { //TODO: make this configurable
|
for (int i = 0; i < 4; i++) { //TODO: make this configurable
|
||||||
joybusDevices[i].type = JOYBUS_CONTROLLER;
|
joybusDevices[i].type = JOYBUS_CONTROLLER;
|
||||||
@@ -44,21 +41,21 @@ void PIF::PollController() {
|
|||||||
bool CLEFT = GET_AXIS(gamepad, SDL_CONTROLLER_AXIS_RIGHTX) <= -127;
|
bool CLEFT = GET_AXIS(gamepad, SDL_CONTROLLER_AXIS_RIGHTX) <= -127;
|
||||||
bool CRIGHT = GET_AXIS(gamepad, SDL_CONTROLLER_AXIS_RIGHTX) >= 127;
|
bool CRIGHT = GET_AXIS(gamepad, SDL_CONTROLLER_AXIS_RIGHTX) >= 127;
|
||||||
|
|
||||||
players[0].controller.a = A;
|
joybusDevices[channel].controller.a = A;
|
||||||
players[0].controller.b = B;
|
joybusDevices[channel].controller.b = B;
|
||||||
players[0].controller.z = Z;
|
joybusDevices[channel].controller.z = Z;
|
||||||
players[0].controller.start = START;
|
joybusDevices[channel].controller.start = START;
|
||||||
players[0].controller.dp_up = DUP;
|
joybusDevices[channel].controller.dp_up = DUP;
|
||||||
players[0].controller.dp_down = DDOWN;
|
joybusDevices[channel].controller.dp_down = DDOWN;
|
||||||
players[0].controller.dp_left = DLEFT;
|
joybusDevices[channel].controller.dp_left = DLEFT;
|
||||||
players[0].controller.dp_right = DRIGHT;
|
joybusDevices[channel].controller.dp_right = DRIGHT;
|
||||||
players[0].controller.joy_reset = L && R && START;
|
joybusDevices[channel].controller.joy_reset = L && R && START;
|
||||||
players[0].controller.l = L;
|
joybusDevices[channel].controller.l = L;
|
||||||
players[0].controller.r = R;
|
joybusDevices[channel].controller.r = R;
|
||||||
players[0].controller.c_up = CUP;
|
joybusDevices[channel].controller.c_up = CUP;
|
||||||
players[0].controller.c_down = CDOWN;
|
joybusDevices[channel].controller.c_down = CDOWN;
|
||||||
players[0].controller.c_left = CLEFT;
|
joybusDevices[channel].controller.c_left = CLEFT;
|
||||||
players[0].controller.c_right = CRIGHT;
|
joybusDevices[channel].controller.c_right = CRIGHT;
|
||||||
|
|
||||||
float xclamped = GET_AXIS(gamepad, SDL_CONTROLLER_AXIS_LEFTX);
|
float xclamped = GET_AXIS(gamepad, SDL_CONTROLLER_AXIS_LEFTX);
|
||||||
if(xclamped < 0) {
|
if(xclamped < 0) {
|
||||||
@@ -78,31 +75,31 @@ void PIF::PollController() {
|
|||||||
|
|
||||||
yclamped *= 86;
|
yclamped *= 86;
|
||||||
|
|
||||||
players[0].controller.joy_x = xclamped;
|
joybusDevices[channel].controller.joy_x = xclamped;
|
||||||
players[0].controller.joy_y = -yclamped;
|
joybusDevices[channel].controller.joy_y = -yclamped;
|
||||||
|
|
||||||
if (players[0].controller.joy_reset) {
|
if (joybusDevices[channel].controller.joy_reset) {
|
||||||
players[0].controller.start = false;
|
joybusDevices[channel].controller.start = false;
|
||||||
players[0].controller.joy_x = 0;
|
joybusDevices[channel].controller.joy_x = 0;
|
||||||
players[0].controller.joy_y = 0;
|
joybusDevices[channel].controller.joy_y = 0;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
const uint8_t* state = SDL_GetKeyboardState(nullptr);
|
const uint8_t* state = SDL_GetKeyboardState(nullptr);
|
||||||
players[0].controller.a = state[SDL_SCANCODE_X];
|
joybusDevices[channel].controller.a = state[SDL_SCANCODE_X];
|
||||||
players[0].controller.b = state[SDL_SCANCODE_C];
|
joybusDevices[channel].controller.b = state[SDL_SCANCODE_C];
|
||||||
players[0].controller.z = state[SDL_SCANCODE_Z];
|
joybusDevices[channel].controller.z = state[SDL_SCANCODE_Z];
|
||||||
players[0].controller.start = state[SDL_SCANCODE_RETURN];
|
joybusDevices[channel].controller.start = state[SDL_SCANCODE_RETURN];
|
||||||
players[0].controller.dp_up = state[SDL_SCANCODE_PAGEUP];
|
joybusDevices[channel].controller.dp_up = state[SDL_SCANCODE_PAGEUP];
|
||||||
players[0].controller.dp_down = state[SDL_SCANCODE_PAGEDOWN];
|
joybusDevices[channel].controller.dp_down = state[SDL_SCANCODE_PAGEDOWN];
|
||||||
players[0].controller.dp_left = state[SDL_SCANCODE_HOME];
|
joybusDevices[channel].controller.dp_left = state[SDL_SCANCODE_HOME];
|
||||||
players[0].controller.dp_right = state[SDL_SCANCODE_END];
|
joybusDevices[channel].controller.dp_right = state[SDL_SCANCODE_END];
|
||||||
players[0].controller.joy_reset = state[SDL_SCANCODE_RETURN] && state[SDL_SCANCODE_A] && state[SDL_SCANCODE_S];
|
joybusDevices[channel].controller.joy_reset = state[SDL_SCANCODE_RETURN] && state[SDL_SCANCODE_A] && state[SDL_SCANCODE_S];
|
||||||
players[0].controller.l = state[SDL_SCANCODE_A];
|
joybusDevices[channel].controller.l = state[SDL_SCANCODE_A];
|
||||||
players[0].controller.r = state[SDL_SCANCODE_S];
|
joybusDevices[channel].controller.r = state[SDL_SCANCODE_S];
|
||||||
players[0].controller.c_up = state[SDL_SCANCODE_I];
|
joybusDevices[channel].controller.c_up = state[SDL_SCANCODE_I];
|
||||||
players[0].controller.c_down = state[SDL_SCANCODE_K];
|
joybusDevices[channel].controller.c_down = state[SDL_SCANCODE_K];
|
||||||
players[0].controller.c_left = state[SDL_SCANCODE_J];
|
joybusDevices[channel].controller.c_left = state[SDL_SCANCODE_J];
|
||||||
players[0].controller.c_right = state[SDL_SCANCODE_L];
|
joybusDevices[channel].controller.c_right = state[SDL_SCANCODE_L];
|
||||||
|
|
||||||
s16 xaxis = 0, yaxis = 0;
|
s16 xaxis = 0, yaxis = 0;
|
||||||
if (state[SDL_SCANCODE_LEFT]) {
|
if (state[SDL_SCANCODE_LEFT]) {
|
||||||
@@ -117,13 +114,13 @@ void PIF::PollController() {
|
|||||||
yaxis = 86;
|
yaxis = 86;
|
||||||
}
|
}
|
||||||
|
|
||||||
players[0].controller.joy_x = xaxis;
|
joybusDevices[channel].controller.joy_x = xaxis;
|
||||||
players[0].controller.joy_y = yaxis;
|
joybusDevices[channel].controller.joy_y = yaxis;
|
||||||
|
|
||||||
if (players[0].controller.joy_reset) {
|
if (joybusDevices[channel].controller.joy_reset) {
|
||||||
players[0].controller.start = false;
|
joybusDevices[channel].controller.start = false;
|
||||||
players[0].controller.joy_x = 0;
|
joybusDevices[channel].controller.joy_x = 0;
|
||||||
players[0].controller.joy_y = 0;
|
joybusDevices[channel].controller.joy_y = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
namespace n64 {
|
|
||||||
struct JoybusDevice;
|
|
||||||
|
|
||||||
extern JoybusDevice players[4];
|
|
||||||
}
|
|
||||||
4
src/backend/netplay/CMakeLists.txt
Normal file
4
src/backend/netplay/CMakeLists.txt
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
file(GLOB SOURCES *.cpp)
|
||||||
|
file(GLOB HEADERS *.hpp)
|
||||||
|
|
||||||
|
add_library(netplay ${SOURCES} ${HEADERS})
|
||||||
5
src/backend/netplay/LAN.cpp
Normal file
5
src/backend/netplay/LAN.cpp
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
#include <Netplay.hpp>
|
||||||
|
|
||||||
|
namespace Netplay {
|
||||||
|
|
||||||
|
}
|
||||||
@@ -27,6 +27,14 @@ static FORCE_INLINE constexpr u32 GetCyclesPerFrame(bool pal) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static FORCE_INLINE constexpr u32 GetVideoFrequency(bool pal) {
|
||||||
|
if (pal) {
|
||||||
|
return 49'656'530;
|
||||||
|
} else {
|
||||||
|
return 48'681'812;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#define HALF_ADDRESS(addr) ((addr) ^ 2)
|
#define HALF_ADDRESS(addr) ((addr) ^ 2)
|
||||||
#define BYTE_ADDRESS(addr) ((addr) ^ 3)
|
#define BYTE_ADDRESS(addr) ((addr) ^ 3)
|
||||||
|
|
||||||
|
|||||||
@@ -48,20 +48,14 @@ void App::Run() {
|
|||||||
case SDL_KEYDOWN:
|
case SDL_KEYDOWN:
|
||||||
switch (event.key.keysym.sym) {
|
switch (event.key.keysym.sym) {
|
||||||
case SDLK_o: {
|
case SDLK_o: {
|
||||||
nfdchar_t *outpath;
|
OpenROMDialog(window, core);
|
||||||
const nfdu8filteritem_t filter{"Nintendo 64 roms/archives", "n64,z64,v64,N64,Z64,V64,zip,tar,rar,7z"};
|
|
||||||
nfdresult_t result = NFD_OpenDialog(&outpath, &filter, 1, nullptr);
|
|
||||||
if (result == NFD_OKAY) {
|
|
||||||
LoadROM(outpath);
|
|
||||||
NFD_FreePath(outpath);
|
|
||||||
}
|
|
||||||
} break;
|
} break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case SDL_DROPFILE: {
|
case SDL_DROPFILE: {
|
||||||
char *droppedDir = event.drop.file;
|
char *droppedDir = event.drop.file;
|
||||||
if (droppedDir) {
|
if (droppedDir) {
|
||||||
LoadROM(droppedDir);
|
window.LoadROM(core, droppedDir);
|
||||||
free(droppedDir);
|
free(droppedDir);
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
|
|||||||
@@ -6,10 +6,6 @@ struct App {
|
|||||||
App();
|
App();
|
||||||
~App() { Util::ClearRPC(); }
|
~App() { Util::ClearRPC(); }
|
||||||
void Run();
|
void Run();
|
||||||
FORCE_INLINE void LoadROM(const std::string& path) {
|
|
||||||
window.LoadROM(core, path);
|
|
||||||
}
|
|
||||||
private:
|
|
||||||
n64::Core core;
|
n64::Core core;
|
||||||
Window window;
|
Window window;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -70,6 +70,7 @@ Settings::~Settings() {
|
|||||||
|
|
||||||
void Settings::RenderWidget(bool& show) {
|
void Settings::RenderWidget(bool& show) {
|
||||||
if(show) {
|
if(show) {
|
||||||
|
static float oldVolumeL = volumeL, oldVolumeR = volumeR;
|
||||||
ImGui::OpenPopup("Settings");
|
ImGui::OpenPopup("Settings");
|
||||||
if(ImGui::BeginPopupModal("Settings", &show)) {
|
if(ImGui::BeginPopupModal("Settings", &show)) {
|
||||||
enum class SelectedSetting { Audio, COUNT };
|
enum class SelectedSetting { Audio, COUNT };
|
||||||
@@ -80,6 +81,22 @@ void Settings::RenderWidget(bool& show) {
|
|||||||
switch (selectedSetting) {
|
switch (selectedSetting) {
|
||||||
case SelectedSetting::Audio:
|
case SelectedSetting::Audio:
|
||||||
ImGui::Checkbox("Lock channels", &lockChannels);
|
ImGui::Checkbox("Lock channels", &lockChannels);
|
||||||
|
ImGui::Checkbox("Mute", &mute);
|
||||||
|
if(mute) {
|
||||||
|
volumeL = 0;
|
||||||
|
volumeR = 0;
|
||||||
|
|
||||||
|
ImGui::BeginDisabled();
|
||||||
|
ImGui::SliderFloat("Volume L", &oldVolumeL, 0, 1, "%.2f", ImGuiSliderFlags_NoInput);
|
||||||
|
if (lockChannels) {
|
||||||
|
oldVolumeR = oldVolumeL;
|
||||||
|
}
|
||||||
|
ImGui::SliderFloat("Volume R", &oldVolumeR, 0, 1, "%.2f", ImGuiSliderFlags_NoInput);
|
||||||
|
ImGui::EndDisabled();
|
||||||
|
} else {
|
||||||
|
volumeL = oldVolumeL;
|
||||||
|
volumeR = oldVolumeR;
|
||||||
|
|
||||||
ImGui::SliderFloat("Volume L", &volumeL, 0, 1, "%.2f", ImGuiSliderFlags_NoInput);
|
ImGui::SliderFloat("Volume L", &volumeL, 0, 1, "%.2f", ImGuiSliderFlags_NoInput);
|
||||||
if (!lockChannels) {
|
if (!lockChannels) {
|
||||||
ImGui::SliderFloat("Volume R", &volumeR, 0, 1, "%.2f", ImGuiSliderFlags_NoInput);
|
ImGui::SliderFloat("Volume R", &volumeR, 0, 1, "%.2f", ImGuiSliderFlags_NoInput);
|
||||||
@@ -89,6 +106,11 @@ void Settings::RenderWidget(bool& show) {
|
|||||||
ImGui::SliderFloat("Volume R", &volumeR, 0, 1, "%.2f", ImGuiSliderFlags_NoInput);
|
ImGui::SliderFloat("Volume R", &volumeR, 0, 1, "%.2f", ImGuiSliderFlags_NoInput);
|
||||||
ImGui::EndDisabled();
|
ImGui::EndDisabled();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
oldVolumeL = volumeL;
|
||||||
|
oldVolumeR = volumeR;
|
||||||
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case SelectedSetting::COUNT:
|
case SelectedSetting::COUNT:
|
||||||
Util::panic("BRUH");
|
Util::panic("BRUH");
|
||||||
|
|||||||
@@ -17,5 +17,6 @@ struct Settings {
|
|||||||
private:
|
private:
|
||||||
float volumeL = 0.0, volumeR = 0.0;
|
float volumeL = 0.0, volumeR = 0.0;
|
||||||
bool lockChannels = true;
|
bool lockChannels = true;
|
||||||
|
bool mute = false;
|
||||||
json settings;
|
json settings;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
#include <Window.hpp>
|
#include <Window.hpp>
|
||||||
#include <nfd.hpp>
|
|
||||||
#include <Core.hpp>
|
#include <Core.hpp>
|
||||||
#include <Audio.hpp>
|
#include <Audio.hpp>
|
||||||
#include <SDL2/SDL.h>
|
#include <SDL2/SDL.h>
|
||||||
@@ -171,14 +170,7 @@ void Window::RenderMainMenuBar(n64::Core &core) {
|
|||||||
|
|
||||||
if (ImGui::BeginMenu("File")) {
|
if (ImGui::BeginMenu("File")) {
|
||||||
if (ImGui::MenuItem("Open", "O")) {
|
if (ImGui::MenuItem("Open", "O")) {
|
||||||
nfdchar_t *outpath;
|
OpenROMDialog(*this, core);
|
||||||
const nfdu8filteritem_t filter{"Nintendo 64 roms", "n64,z64,v64,N64,Z64,V64"};
|
|
||||||
nfdresult_t result = NFD_OpenDialog(&outpath, &filter, 1, nullptr);
|
|
||||||
if (result == NFD_OKAY) {
|
|
||||||
LoadROM(core, outpath);
|
|
||||||
Util::UpdateRPC(Util::Playing, gameName);
|
|
||||||
NFD_FreePath(outpath);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (ImGui::MenuItem("Dump RDRAM")) {
|
if (ImGui::MenuItem("Dump RDRAM")) {
|
||||||
core.cpu.mem.DumpRDRAM();
|
core.cpu.mem.DumpRDRAM();
|
||||||
|
|||||||
@@ -6,6 +6,8 @@
|
|||||||
#include <SDL2/SDL.h>
|
#include <SDL2/SDL.h>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <frontend/imgui/Settings.hpp>
|
#include <frontend/imgui/Settings.hpp>
|
||||||
|
#include <nfd.hpp>
|
||||||
|
#include "Discord.hpp"
|
||||||
|
|
||||||
struct Window {
|
struct Window {
|
||||||
explicit Window(n64::Core& core);
|
explicit Window(n64::Core& core);
|
||||||
@@ -17,12 +19,12 @@ struct Window {
|
|||||||
Settings settings;
|
Settings settings;
|
||||||
void LoadROM(n64::Core& core, const std::string& path);
|
void LoadROM(n64::Core& core, const std::string& path);
|
||||||
bool done = false;
|
bool done = false;
|
||||||
|
std::string gameName{};
|
||||||
private:
|
private:
|
||||||
bool showSettings = false;
|
bool showSettings = false;
|
||||||
SDL_Window* window{};
|
SDL_Window* window{};
|
||||||
std::string windowTitle{"Kaizen"};
|
std::string windowTitle{"Kaizen"};
|
||||||
std::string shadowWindowTitle{windowTitle};
|
std::string shadowWindowTitle{windowTitle};
|
||||||
std::string gameName{};
|
|
||||||
void InitSDL();
|
void InitSDL();
|
||||||
void InitImgui();
|
void InitImgui();
|
||||||
void Render(n64::Core& core);
|
void Render(n64::Core& core);
|
||||||
@@ -38,3 +40,13 @@ private:
|
|||||||
|
|
||||||
u32 minImageCount = 2;
|
u32 minImageCount = 2;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static void FORCE_INLINE OpenROMDialog(Window& window, n64::Core& core) {
|
||||||
|
nfdchar_t *outpath;
|
||||||
|
const nfdu8filteritem_t filter{"Nintendo 64 roms/archives", "n64,z64,v64,N64,Z64,V64,zip,tar,rar,7z"};
|
||||||
|
nfdresult_t result = NFD_OpenDialog(&outpath, &filter, 1, nullptr);
|
||||||
|
if (result == NFD_OKAY) {
|
||||||
|
window.LoadROM(core, outpath);
|
||||||
|
NFD_FreePath(outpath);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -8,7 +8,7 @@ int main(int argc, char** argv) {
|
|||||||
if(argc > 2) {
|
if(argc > 2) {
|
||||||
LoadTAS(argv[2]);
|
LoadTAS(argv[2]);
|
||||||
}
|
}
|
||||||
app->LoadROM(argv[1]);
|
app->window.LoadROM(app->core, argv[1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
app->Run();
|
app->Run();
|
||||||
|
|||||||
@@ -8,7 +8,11 @@ enum LogLevel : u8 {
|
|||||||
Trace, Info, Debug, Warn, Error
|
Trace, Info, Debug, Warn, Error
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#ifndef _NDEBUG
|
||||||
|
static constexpr auto globalLogLevel = Debug;
|
||||||
|
#else
|
||||||
static constexpr auto globalLogLevel = Warn;
|
static constexpr auto globalLogLevel = Warn;
|
||||||
|
#endif
|
||||||
|
|
||||||
template <LogLevel messageType = Info, typename ...Args>
|
template <LogLevel messageType = Info, typename ...Args>
|
||||||
constexpr void print(const std::string& fmt, Args... args) {
|
constexpr void print(const std::string& fmt, Args... args) {
|
||||||
@@ -43,6 +47,11 @@ constexpr void panic(const std::string& fmt, Args... args) {
|
|||||||
exit(-1);
|
exit(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename ...Args>
|
||||||
|
constexpr void error(const std::string& fmt, Args... args) {
|
||||||
|
print<Error>(fmt + "\n", args...);
|
||||||
|
}
|
||||||
|
|
||||||
template <typename ...Args>
|
template <typename ...Args>
|
||||||
constexpr void warn(const std::string& fmt, Args... args) {
|
constexpr void warn(const std::string& fmt, Args... args) {
|
||||||
print<Warn>(fmt + "\n", args...);
|
print<Warn>(fmt + "\n", args...);
|
||||||
@@ -57,4 +66,9 @@ template <typename ...Args>
|
|||||||
constexpr void debug(const std::string& fmt, Args... args) {
|
constexpr void debug(const std::string& fmt, Args... args) {
|
||||||
print<Debug>(fmt + "\n", args...);
|
print<Debug>(fmt + "\n", args...);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename ...Args>
|
||||||
|
constexpr void trace(const std::string& fmt, Args... args) {
|
||||||
|
print<Trace>(fmt + "\n", args...);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user