start this from scratch

This commit is contained in:
Simone
2024-01-18 12:31:53 +01:00
parent c4f021cb9d
commit af7a6c004b
24 changed files with 116 additions and 921 deletions

View File

@@ -2,7 +2,7 @@
#include <log.hpp>
#include <core/Mem.hpp>
#include <core/registers/Registers.hpp>
#include <core/Audio.hpp>
#include <Audio.hpp>
namespace n64 {
void AI::Reset() {

View File

@@ -0,0 +1,87 @@
#include <Audio.hpp>
#include <SDL2/SDL_audio.h>
#include <log.hpp>
namespace n64 {
#define AUDIO_SAMPLE_RATE 44100
#define SYSTEM_SAMPLE_FORMAT AUDIO_F32SYS
#define SYSTEM_SAMPLE_SIZE 4
#define BYTES_PER_HALF_SECOND (((float)AUDIO_SAMPLE_RATE / 2) * SYSTEM_SAMPLE_SIZE)
static SDL_AudioStream* audioStream = nullptr;
SDL_mutex* audioStreamMutex;
SDL_AudioSpec audioSpec;
SDL_AudioSpec request;
SDL_AudioDeviceID audioDev{};
#define LockAudioMutex() SDL_LockMutex(audioStreamMutex)
#define UnlockAudioMutex() SDL_UnlockMutex(audioStreamMutex)
void audioCallback(void*, Uint8* stream, int length) {
int gotten = 0;
LockAudioMutex();
int available = SDL_AudioStreamAvailable(audioStream);
if (available > 0) {
gotten = SDL_AudioStreamGet(audioStream, stream, length);
}
UnlockAudioMutex();
int gotten_samples = (int)(gotten / sizeof(float));
auto* out = (float*)stream;
out += gotten_samples;
for (int i = gotten_samples; i < length / sizeof(float); i++) {
float sample = 0;
*out++ = sample;
}
}
void InitAudio() {
AdjustSampleRate(AUDIO_SAMPLE_RATE);
memset(&request, 0, sizeof(request));
request.freq = AUDIO_SAMPLE_RATE;
request.format = SYSTEM_SAMPLE_FORMAT;
request.channels = 2;
request.samples = 1024;
request.callback = audioCallback;
request.userdata = nullptr;
if(!audioDev) {
audioDev = SDL_OpenAudioDevice(nullptr, 0, &request, &audioSpec, 0);
}
if(!audioDev) {
Util::panic("Failed to initialize SDL Audio: {}", SDL_GetError());
}
SDL_PauseAudioDevice(audioDev, false);
audioStreamMutex = SDL_CreateMutex();
if(!audioStreamMutex) {
Util::panic("Unable to initialize audio mutex: {}", SDL_GetError());
}
}
void PushSample(float left, float volumeL, float right, float volumeR) {
float adjustedL = left * volumeL;
float adjustedR = right * volumeR;
float samples[2]{ adjustedL, adjustedR };
float availableBytes = SDL_AudioStreamAvailable(audioStream);
if(availableBytes <= BYTES_PER_HALF_SECOND) {
SDL_AudioStreamPut(audioStream, samples, 2 * sizeof(float));
}
}
void AdjustSampleRate(int sampleRate) {
LockAudioMutex();
if(audioStream) SDL_FreeAudioStream(audioStream);
audioStream = SDL_NewAudioStream(AUDIO_F32SYS, 2, sampleRate, SYSTEM_SAMPLE_FORMAT, 2, AUDIO_SAMPLE_RATE);
UnlockAudioMutex();
}
}

View File

@@ -0,0 +1,8 @@
#pragma once
#include <common.hpp>
namespace n64 {
void PushSample(float, float, float, float);
void InitAudio();
void AdjustSampleRate(int);
}

View File

@@ -1,5 +1,5 @@
#include <PIF.hpp>
#include <MupenMovie.hpp>
#include <PIF/MupenMovie.hpp>
#include <Netplay.hpp>
#include <log.hpp>
#include <SDL2/SDL_keyboard.h>

View File

@@ -0,0 +1,180 @@
#include <PIF/MupenMovie.hpp>
#include <log.hpp>
struct TASMovieHeader {
u8 signature[4];
u32 version;
u32 uid;
u32 numFrames;
u32 rerecords;
u8 fps;
u8 numControllers;
u8 reserved1;
u8 reserved2;
u32 numInputSamples;
uint16_t startType;
u8 reserved3;
u8 reserved4;
u32 controllerFlags;
u8 reserved5[160];
char romName[32];
u32 romCrc32;
uint16_t romCountryCode;
u8 reserved6[56];
// 122 64-byte ASCII string: name of video plugin used when recording, directly from plugin
char video_plugin_name[64];
// 162 64-byte ASCII string: name of sound plugin used when recording, directly from plugin
char audio_plugin_name[64];
// 1A2 64-byte ASCII string: name of input plugin used when recording, directly from plugin
char input_plugin_name[64];
// 1E2 64-byte ASCII string: name of rsp plugin used when recording, directly from plugin
char rsp_plugin_name[64];
// 222 222-byte UTF-8 string: author name info
char author_name[222];
// 300 256-byte UTF-8 string: author movie description info
char movie_description[256];
} __attribute__((packed));
static_assert(sizeof(TASMovieHeader) == 1024);
union TASMovieControllerData {
struct {
bool dpad_right: 1;
bool dpad_left: 1;
bool dpad_down: 1;
bool dpad_up: 1;
bool start: 1;
bool z: 1;
bool b: 1;
bool a: 1;
bool c_right: 1;
bool c_left: 1;
bool c_down: 1;
bool c_up: 1;
bool r: 1;
bool l: 1;
u8: 2;
s8 analog_x: 8;
s8 analog_y: 8;
};
u32 raw;
} __attribute__((packed));
static_assert(sizeof(TASMovieControllerData) == 4);
static u8* loaded_tas_movie = nullptr;
static size_t loaded_tas_movie_size = 0;
TASMovieHeader loaded_tas_movie_header;
uint32_t loaded_tas_movie_index = 0;
void LoadTAS(const char* filename) {
FILE *fp = fopen(filename, "rb");
if (!fp) {
Util::panic("Error opening the movie file {}! Are you sure it's a valid movie and that it exists?", filename);
}
fseek(fp, 0, SEEK_END);
size_t size = ftell(fp);
fseek(fp, 0, SEEK_SET);
u8 *buf = (u8*)malloc(size);
fread(buf, size, 1, fp);
loaded_tas_movie = buf;
loaded_tas_movie_size = size;
if (!loaded_tas_movie) {
Util::panic("Error loading movie!");
}
memcpy(&loaded_tas_movie_header, buf, sizeof(TASMovieHeader));
if (loaded_tas_movie_header.signature[0] != 0x4D || loaded_tas_movie_header.signature[1] != 0x36 || loaded_tas_movie_header.signature[2] != 0x34 || loaded_tas_movie_header.signature[3] != 0x1A) {
Util::panic("Failed to load movie: incorrect signature. Are you sure this is a valid movie?");
}
if (loaded_tas_movie_header.version != 3) {
Util::panic("This movie is version {}: only version 3 is supported.", loaded_tas_movie_header.version);
}
if (loaded_tas_movie_header.startType != 2) {
Util::panic("Movie start type is {} - only movies with a start type of 2 are supported (start at power on)", loaded_tas_movie_header.startType);
}
// TODO: check ROM CRC32 here
Util::info("Loaded movie '{}' ", loaded_tas_movie_header.movie_description);
Util::info("by {}", loaded_tas_movie_header.author_name);
Util::info("{} controller(s) connected", loaded_tas_movie_header.numControllers);
if (loaded_tas_movie_header.numControllers != 1) {
Util::panic("Currently, only movies with 1 controller connected are supported.");
}
loaded_tas_movie_index = sizeof(TASMovieHeader) - 4; // skip header
}
bool TasMovieLoaded() {
return loaded_tas_movie != nullptr;
}
FORCE_INLINE void LogController(const n64::Controller& controller) {
Util::debug("c_right: {}", controller.c_right);
Util::debug("c_left: {}", controller.c_left);
Util::debug("c_down: {}", controller.c_down);
Util::debug("c_up: {}", controller.c_up);
Util::debug("r: {}", controller.r);
Util::debug("l: {}", controller.l);
Util::debug("dp_right: {}", controller.dp_right);
Util::debug("dp_left: {}", controller.dp_left);
Util::debug("dp_down: {}", controller.dp_down);
Util::debug("dp_up: {}", controller.dp_up);
Util::debug("z: {}", controller.z);
Util::debug("b: {}", controller.b);
Util::debug("a: {}", controller.a);
Util::debug("start: {}", controller.start);
Util::debug("joy_x: {}", controller.joy_x);
Util::debug("joy_y: {}", controller.joy_y);
}
n64::Controller TasNextInputs() {
if (loaded_tas_movie_index + sizeof(TASMovieControllerData) > loaded_tas_movie_size) {
loaded_tas_movie = nullptr;
n64::Controller empty_controller{};
memset(&empty_controller, 0, sizeof(n64::Controller));
return empty_controller;
}
TASMovieControllerData movie_cdata{};
memcpy(&movie_cdata, loaded_tas_movie + loaded_tas_movie_index, sizeof(TASMovieControllerData));
loaded_tas_movie_index += sizeof(TASMovieControllerData);
n64::Controller controller{};
memset(&controller, 0, sizeof(controller));
controller.c_right = movie_cdata.c_right;
controller.c_left = movie_cdata.c_left;
controller.c_down = movie_cdata.c_down;
controller.c_up = movie_cdata.c_up;
controller.r = movie_cdata.r;
controller.l = movie_cdata.l;
controller.dp_right = movie_cdata.dpad_right;
controller.dp_left = movie_cdata.dpad_left;
controller.dp_down = movie_cdata.dpad_down;
controller.dp_up = movie_cdata.dpad_up;
controller.z = movie_cdata.z;
controller.b = movie_cdata.b;
controller.a = movie_cdata.a;
controller.start = movie_cdata.start;
controller.joy_x = movie_cdata.analog_x;
controller.joy_y = movie_cdata.analog_y;
LogController(controller);
return controller;
}

View File

@@ -0,0 +1,6 @@
#pragma once
#include <backend/core/mmio/PIF.hpp>
void LoadTAS(const char* filename);
n64::Controller TasNextInputs();
bool TasMovieLoaded();