Code reformatting (80-char limit); C-style comments

This commit is contained in:
twinaphex 2014-08-20 17:18:43 +02:00
parent cb09818d71
commit 1d043121e2
6 changed files with 400 additions and 241 deletions

View File

@ -53,14 +53,15 @@ static void autosave_thread(void *data)
if (differ)
{
// Should probably deal with this more elegantly.
/* Should probably deal with this more elegantly. */
FILE *file = fopen(save->path, "wb");
if (file)
{
// Avoid spamming down stderr ... :)
/* Avoid spamming down stderr ... */
if (first_log)
{
RARCH_LOG("Autosaving SRAM to \"%s\", will continue to check every %u seconds ...\n", save->path, save->interval);
RARCH_LOG("Autosaving SRAM to \"%s\", will continue to check every %u seconds ...\n",
save->path, save->interval);
first_log = false;
}
else
@ -76,13 +77,17 @@ static void autosave_thread(void *data)
}
slock_lock(save->cond_lock);
if (!save->quit)
scond_wait_timeout(save->cond, save->cond_lock, save->interval * 1000000LL);
scond_wait_timeout(save->cond, save->cond_lock,
save->interval * 1000000LL);
slock_unlock(save->cond_lock);
}
}
autosave_t *autosave_new(const char *path, const void *data, size_t size, unsigned interval)
autosave_t *autosave_new(const char *path, const void *data, size_t size,
unsigned interval)
{
autosave_t *handle = (autosave_t*)calloc(1, sizeof(*handle));
if (!handle)

View File

@ -39,7 +39,8 @@ const ffemu_backend_t *ffemu_find_backend(const char *ident)
return NULL;
}
bool ffemu_init_first(const ffemu_backend_t **backend, void **data, const struct ffemu_params *params)
bool ffemu_init_first(const ffemu_backend_t **backend, void **data,
const struct ffemu_params *params)
{
unsigned i;
for (i = 0; ffemu_backends[i]; i++)

View File

@ -31,36 +31,37 @@ enum ffemu_pix_format
FFEMU_PIX_ARGB8888
};
// Parameters passed to ffemu_new()
/* Parameters passed to ffemu_new() */
struct ffemu_params
{
// FPS of input video.
/* FPS of input video. */
double fps;
// Sample rate of input audio.
/* Sample rate of input audio. */
double samplerate;
// Desired output resolution.
/* Desired output resolution. */
unsigned out_width;
unsigned out_height;
// Total size of framebuffer used in input.
/* Total size of framebuffer used in input. */
unsigned fb_width;
unsigned fb_height;
// Aspect ratio of input video. Parameters are passed to the muxer,
// the video itself is not scaled.
/* Aspect ratio of input video. Parameters are passed to the muxer,
* the video itself is not scaled.
*/
float aspect_ratio;
// Audio channels.
/* Audio channels. */
unsigned channels;
// Input pixel format.
/* Input pixel format. */
enum ffemu_pix_format pix_fmt;
// Filename to dump to.
/* Filename to dump to. */
const char *filename;
// Path to config. Optional.
/* Path to config. Optional. */
const char *config;
};
@ -83,7 +84,7 @@ typedef struct ffemu_backend
{
void *(*init)(const struct ffemu_params *params);
void (*free)(void *data);
bool (*push_video)(void *data, const struct ffemu_video_data *video_data);
bool (*push_video)(void *data,const struct ffemu_video_data *video_data);
bool (*push_audio)(void *data, const struct ffemu_audio_data *audio_data);
bool (*finalize)(void *data);
const char *ident;
@ -92,7 +93,8 @@ typedef struct ffemu_backend
extern const ffemu_backend_t ffemu_ffmpeg;
const ffemu_backend_t *ffemu_find_backend(const char *ident);
bool ffemu_init_first(const ffemu_backend_t **backend, void **data, const struct ffemu_params *params);
bool ffemu_init_first(const ffemu_backend_t **backend, void **data,
const struct ffemu_params *params);
#ifdef __cplusplus
}

View File

@ -105,9 +105,10 @@ struct ff_audio_info
uint8_t *outbuf;
size_t outbuf_size;
// Most lossy audio codecs only support certain sampling rates.
// Could use libswresample, but it doesn't support floating point ratios. :(
// Use either S16 or (planar) float for simplicity.
/* Most lossy audio codecs only support certain sampling rates.
* Could use libswresample, but it doesn't support floating point ratios.
* Use either S16 or (planar) float for simplicity.
*/
const rarch_resampler_t *resampler;
void *resampler_data;
@ -150,7 +151,7 @@ struct ff_config_param
unsigned scale_factor;
bool audio_enable;
// Keep same naming conventions as libavcodec.
/* Keep same naming conventions as libavcodec. */
bool audio_qscale;
int audio_global_quality;
int audio_bit_rate;
@ -183,7 +184,8 @@ typedef struct ffmpeg
volatile bool can_sleep;
} ffmpeg_t;
static bool ffmpeg_codec_has_sample_format(enum AVSampleFormat fmt, const enum AVSampleFormat *fmts)
static bool ffmpeg_codec_has_sample_format(enum AVSampleFormat fmt,
const enum AVSampleFormat *fmts)
{
unsigned i;
for (i = 0; fmts[i] != AV_SAMPLE_FMT_NONE; i++)
@ -192,7 +194,8 @@ static bool ffmpeg_codec_has_sample_format(enum AVSampleFormat fmt, const enum A
return false;
}
static void ffmpeg_audio_resolve_format(struct ff_audio_info *audio, const AVCodec *codec)
static void ffmpeg_audio_resolve_format(struct ff_audio_info *audio,
const AVCodec *codec)
{
audio->codec->sample_fmt = AV_SAMPLE_FMT_NONE;
@ -227,18 +230,19 @@ static void ffmpeg_audio_resolve_format(struct ff_audio_info *audio, const AVCod
audio->sample_size = audio->use_float ? sizeof(float) : sizeof(int16_t);
}
static void ffmpeg_audio_resolve_sample_rate(ffmpeg_t *handle, const AVCodec *codec)
static void ffmpeg_audio_resolve_sample_rate(ffmpeg_t *handle,
const AVCodec *codec)
{
unsigned i;
struct ff_config_param *params = &handle->config;
struct ffemu_params *param = &handle->params;
// We'll have to force resampling to some supported sampling rate.
/* We'll have to force resampling to some supported sampling rate. */
if (codec->supported_samplerates && !params->sample_rate)
{
int input_rate = (int)param->samplerate;
// Favor closest sampling rate, but always prefer ratio > 1.0.
/* Favor closest sampling rate, but always prefer ratio > 1.0. */
int best_rate = codec->supported_samplerates[0];
int best_diff = best_rate - input_rate;
@ -271,10 +275,12 @@ static bool ffmpeg_init_audio(ffmpeg_t *handle)
struct ff_video_info *video = &handle->video;
struct ffemu_params *param = &handle->params;
AVCodec *codec = avcodec_find_encoder_by_name(*params->acodec ? params->acodec : "flac");
AVCodec *codec = avcodec_find_encoder_by_name(
*params->acodec ? params->acodec : "flac");
if (!codec)
{
RARCH_ERR("[FFmpeg]: Cannot find acodec %s.\n", *params->acodec ? params->acodec : "flac");
RARCH_ERR("[FFmpeg]: Cannot find acodec %s.\n",
*params->acodec ? params->acodec : "flac");
return false;
}
@ -284,7 +290,8 @@ static bool ffmpeg_init_audio(ffmpeg_t *handle)
audio->codec->codec_type = AVMEDIA_TYPE_AUDIO;
audio->codec->channels = param->channels;
audio->codec->channel_layout = param->channels > 1 ? AV_CH_LAYOUT_STEREO : AV_CH_LAYOUT_MONO;
audio->codec->channel_layout = param->channels > 1
? AV_CH_LAYOUT_STEREO : AV_CH_LAYOUT_MONO;
ffmpeg_audio_resolve_format(audio, codec);
ffmpeg_audio_resolve_sample_rate(handle, codec);
@ -315,7 +322,7 @@ static bool ffmpeg_init_audio(ffmpeg_t *handle)
else if (params->audio_bit_rate)
audio->codec->bit_rate = params->audio_bit_rate;
// Allow experimental codecs.
/* Allow experimental codecs. */
audio->codec->strict_std_compliance = FF_COMPLIANCE_EXPERIMENTAL;
if (handle->muxer.ctx->oformat->flags & AVFMT_GLOBALHEADER)
@ -324,7 +331,7 @@ static bool ffmpeg_init_audio(ffmpeg_t *handle)
if (avcodec_open2(audio->codec, codec, params->audio_opts ? &params->audio_opts : NULL) != 0)
return false;
if (!audio->codec->frame_size) // If not set (PCM), just set something.
if (!audio->codec->frame_size) /* If not set (PCM), just set something. */
audio->codec->frame_size = 1024;
audio->buffer = (uint8_t*)av_malloc(
@ -332,7 +339,9 @@ static bool ffmpeg_init_audio(ffmpeg_t *handle)
audio->codec->channels *
audio->sample_size);
//RARCH_LOG("[FFmpeg]: Audio frame size: %d.\n", audio->codec->frame_size);
#if 0
RARCH_LOG("[FFmpeg]: Audio frame size: %d.\n", audio->codec->frame_size);
#endif
if (!audio->buffer)
return false;
@ -357,23 +366,25 @@ static bool ffmpeg_init_video(ffmpeg_t *handle)
codec = avcodec_find_encoder_by_name(params->vcodec);
else
{
// By default, lossless video.
/* By default, lossless video. */
av_dict_set(&params->video_opts, "qp", "0", 0);
codec = avcodec_find_encoder_by_name("libx264rgb");
}
if (!codec)
{
RARCH_ERR("[FFmpeg]: Cannot find vcodec %s.\n", *params->vcodec ? params->vcodec : "libx264rgb");
RARCH_ERR("[FFmpeg]: Cannot find vcodec %s.\n",
*params->vcodec ? params->vcodec : "libx264rgb");
return false;
}
video->encoder = codec;
// Don't use swscaler unless format is not something "in-house" scaler supports.
// libswscale doesn't scale RGB -> RGB correctly (goes via YUV first), and it's non-trivial to fix
// upstream as it's heavily geared towards YUV.
// If we're dealing with strange formats or YUV, just use libswscale.
/* Don't use swscaler unless format is not something "in-house" scaler supports.
* libswscale doesn't scale RGB -> RGB correctly (goes via YUV first), and it's non-trivial to fix
* upstream as it's heavily geared towards YUV.
* If we're dealing with strange formats or YUV, just use libswscale.
*/
if (params->out_pix_fmt != PIX_FMT_NONE)
{
video->pix_fmt = params->out_pix_fmt;
@ -394,7 +405,7 @@ static bool ffmpeg_init_video(ffmpeg_t *handle)
break;
}
}
else // Use BGR24 as default out format.
else /* Use BGR24 as default out format. */
{
video->pix_fmt = PIX_FMT_BGR24;
video->scaler.out_fmt = SCALER_FMT_BGR24;
@ -426,15 +437,16 @@ static bool ffmpeg_init_video(ffmpeg_t *handle)
video->codec = avcodec_alloc_context3(codec);
// Useful to set scale_factor to 2 for chroma subsampled formats to maintain full chroma resolution.
// (Or just use 4:4:4 or RGB ...)
/* Useful to set scale_factor to 2 for chroma subsampled formats to
* maintain full chroma resolution. (Or just use 4:4:4 or RGB ...)
*/
param->out_width *= params->scale_factor;
param->out_height *= params->scale_factor;
video->codec->codec_type = AVMEDIA_TYPE_VIDEO;
video->codec->width = param->out_width;
video->codec->height = param->out_height;
video->codec->time_base = av_d2q((double)params->frame_drop_ratio / param->fps, 1000000); // Arbitrary big number.
video->codec->time_base = av_d2q((double)params->frame_drop_ratio /param->fps, 1000000); /* Arbitrary big number. */
video->codec->sample_aspect_ratio = av_d2q(param->aspect_ratio * param->out_height / param->out_width, 255);
video->codec->pix_fmt = video->pix_fmt;
@ -451,25 +463,30 @@ static bool ffmpeg_init_video(ffmpeg_t *handle)
if (handle->muxer.ctx->oformat->flags & AVFMT_GLOBALHEADER)
video->codec->flags |= CODEC_FLAG_GLOBAL_HEADER;
if (avcodec_open2(video->codec, codec, params->video_opts ? &params->video_opts : NULL) != 0)
if (avcodec_open2(video->codec, codec, params->video_opts ?
&params->video_opts : NULL) != 0)
return false;
// Allocate a big buffer :p ffmpeg API doesn't seem to give us some clues how big this buffer should be.
/* Allocate a big buffer. ffmpeg API doesn't seem to give us some
* clues how big this buffer should be.
*/
video->outbuf_size = 1 << 23;
video->outbuf = (uint8_t*)av_malloc(video->outbuf_size);
video->frame_drop_ratio = params->frame_drop_ratio;
size_t size = avpicture_get_size(video->pix_fmt, param->out_width, param->out_height);
size_t size = avpicture_get_size(video->pix_fmt, param->out_width,
param->out_height);
video->conv_frame_buf = (uint8_t*)av_malloc(size);
video->conv_frame = av_frame_alloc();
avpicture_fill((AVPicture*)video->conv_frame, video->conv_frame_buf, video->pix_fmt,
param->out_width, param->out_height);
avpicture_fill((AVPicture*)video->conv_frame, video->conv_frame_buf,
video->pix_fmt, param->out_width, param->out_height);
return true;
}
static bool ffmpeg_init_config(struct ff_config_param *params, const char *config)
static bool ffmpeg_init_config(struct ff_config_param *params,
const char *config)
{
params->out_pix_fmt = PIX_FMT_NONE;
params->scale_factor = 1;
@ -486,14 +503,17 @@ static bool ffmpeg_init_config(struct ff_config_param *params, const char *confi
return false;
}
config_get_array(params->conf, "vcodec", params->vcodec, sizeof(params->vcodec));
config_get_array(params->conf, "acodec", params->acodec, sizeof(params->acodec));
config_get_array(params->conf, "format", params->format, sizeof(params->format));
config_get_array(params->conf, "vcodec", params->vcodec,
sizeof(params->vcodec));
config_get_array(params->conf, "acodec", params->acodec,
sizeof(params->acodec));
config_get_array(params->conf, "format", params->format,
sizeof(params->format));
config_get_uint(params->conf, "threads", &params->threads);
if (!config_get_uint(params->conf, "frame_drop_ratio", &params->frame_drop_ratio)
|| !params->frame_drop_ratio)
if (!config_get_uint(params->conf, "frame_drop_ratio",
&params->frame_drop_ratio) || !params->frame_drop_ratio)
params->frame_drop_ratio = 1;
if (!config_get_bool(params->conf, "audio_enable", &params->audio_enable))
@ -502,9 +522,11 @@ static bool ffmpeg_init_config(struct ff_config_param *params, const char *confi
config_get_uint(params->conf, "sample_rate", &params->sample_rate);
config_get_uint(params->conf, "scale_factor", &params->scale_factor);
params->audio_qscale = config_get_int(params->conf, "audio_global_quality", &params->audio_global_quality);
params->audio_qscale = config_get_int(params->conf, "audio_global_quality",
&params->audio_global_quality);
config_get_int(params->conf, "audio_bit_rate", &params->audio_bit_rate);
params->video_qscale = config_get_int(params->conf, "video_global_quality", &params->video_global_quality);
params->video_qscale = config_get_int(params->conf, "video_global_quality",
&params->video_global_quality);
config_get_int(params->conf, "video_bit_rate", &params->video_bit_rate);
char pix_fmt[64] = {0};
@ -564,19 +586,23 @@ static bool ffmpeg_init_muxer_pre(ffmpeg_t *handle)
static bool ffmpeg_init_muxer_post(ffmpeg_t *handle)
{
AVStream *stream = avformat_new_stream(handle->muxer.ctx, handle->video.encoder);
AVStream *stream = avformat_new_stream(handle->muxer.ctx,
handle->video.encoder);
stream->codec = handle->video.codec;
handle->muxer.vstream = stream;
handle->muxer.vstream->sample_aspect_ratio = handle->video.codec->sample_aspect_ratio;
handle->muxer.vstream->sample_aspect_ratio =
handle->video.codec->sample_aspect_ratio;
if (handle->config.audio_enable)
{
stream = avformat_new_stream(handle->muxer.ctx, handle->audio.encoder);
stream = avformat_new_stream(handle->muxer.ctx,
handle->audio.encoder);
stream->codec = handle->audio.codec;
handle->muxer.astream = stream;
}
av_dict_set(&handle->muxer.ctx->metadata, "title", "RetroArch video dump", 0);
av_dict_set(&handle->muxer.ctx->metadata, "title",
"RetroArch video dump", 0);
return avformat_write_header(handle->muxer.ctx, NULL) >= 0;
}
@ -590,7 +616,8 @@ static bool init_thread(ffmpeg_t *handle)
handle->lock = slock_new();
handle->cond_lock = slock_new();
handle->cond = scond_new();
handle->audio_fifo = fifo_new(32000 * sizeof(int16_t) * handle->params.channels * MAX_FRAMES / 60); // Some arbitrary max size.
handle->audio_fifo = fifo_new(32000 * sizeof(int16_t) *
handle->params.channels * MAX_FRAMES / 60); /* Some arbitrary max size. */
handle->attr_fifo = fifo_new(sizeof(struct ffemu_video_data) * MAX_FRAMES);
handle->video_fifo = fifo_new(handle->params.fb_width * handle->params.fb_height *
handle->video.pix_size * MAX_FRAMES);
@ -732,7 +759,8 @@ error:
return NULL;
}
static bool ffmpeg_push_video(void *data, const struct ffemu_video_data *video_data)
static bool ffmpeg_push_video(void *data,
const struct ffemu_video_data *video_data)
{
unsigned y;
bool drop_frame;
@ -775,7 +803,9 @@ static bool ffmpeg_push_video(void *data, const struct ffemu_video_data *video_d
slock_lock(handle->lock);
// Tightly pack our frame to conserve memory. libretro tends to use a very large pitch.
/* Tightly pack our frame to conserve memory.
* libretro tends to use a very large pitch.
*/
struct ffemu_video_data attr_data = *video_data;
if (attr_data.is_dupe)
@ -787,7 +817,8 @@ static bool ffmpeg_push_video(void *data, const struct ffemu_video_data *video_d
int offset = 0;
for (y = 0; y < attr_data.height; y++, offset += video_data->pitch)
fifo_write(handle->video_fifo, (const uint8_t*)video_data->data + offset, attr_data.pitch);
fifo_write(handle->video_fifo,
(const uint8_t*)video_data->data + offset, attr_data.pitch);
slock_unlock(handle->lock);
scond_signal(handle->cond);
@ -795,7 +826,8 @@ static bool ffmpeg_push_video(void *data, const struct ffemu_video_data *video_d
return true;
}
static bool ffmpeg_push_audio(void *data, const struct ffemu_audio_data *audio_data)
static bool ffmpeg_push_audio(void *data,
const struct ffemu_audio_data *audio_data)
{
ffmpeg_t *handle = (ffmpeg_t*)data;
@ -814,7 +846,8 @@ static bool ffmpeg_push_audio(void *data, const struct ffemu_audio_data *audio_d
if (!handle->alive)
return false;
if (avail >= audio_data->frames * handle->params.channels * sizeof(int16_t))
if (avail >= audio_data->frames * handle->params.channels
* sizeof(int16_t))
break;
slock_lock(handle->cond_lock);
@ -831,7 +864,8 @@ static bool ffmpeg_push_audio(void *data, const struct ffemu_audio_data *audio_d
}
slock_lock(handle->lock);
fifo_write(handle->audio_fifo, audio_data->data, audio_data->frames * handle->params.channels * sizeof(int16_t));
fifo_write(handle->audio_fifo, audio_data->data,
audio_data->frames * handle->params.channels * sizeof(int16_t));
slock_unlock(handle->lock);
scond_signal(handle->cond);
@ -872,30 +906,37 @@ static bool encode_video(ffmpeg_t *handle, AVPacket *pkt, AVFrame *frame)
return true;
}
static void ffmpeg_scale_input(ffmpeg_t *handle, const struct ffemu_video_data *data)
static void ffmpeg_scale_input(ffmpeg_t *handle,
const struct ffemu_video_data *data)
{
// Attempt to preserve more information if we scale down.
bool shrunk = handle->params.out_width < data->width || handle->params.out_height < data->height;
/* Attempt to preserve more information if we scale down. */
bool shrunk = handle->params.out_width < data->width
|| handle->params.out_height < data->height;
if (handle->video.use_sws)
{
handle->video.sws = sws_getCachedContext(handle->video.sws, data->width, data->height, handle->video.in_pix_fmt,
handle->params.out_width, handle->params.out_height, handle->video.pix_fmt,
handle->video.sws = sws_getCachedContext(handle->video.sws,
data->width, data->height, handle->video.in_pix_fmt,
handle->params.out_width, handle->params.out_height,
handle->video.pix_fmt,
shrunk ? SWS_BILINEAR : SWS_POINT, NULL, NULL, NULL);
int linesize = data->pitch;
sws_scale(handle->video.sws, (const uint8_t* const*)&data->data, &linesize, 0,
data->height, handle->video.conv_frame->data, handle->video.conv_frame->linesize);
sws_scale(handle->video.sws, (const uint8_t* const*)&data->data,
&linesize, 0, data->height, handle->video.conv_frame->data,
handle->video.conv_frame->linesize);
}
else
{
if ((int)data->width != handle->video.scaler.in_width || (int)data->height != handle->video.scaler.in_height)
if ((int)data->width != handle->video.scaler.in_width
|| (int)data->height != handle->video.scaler.in_height)
{
handle->video.scaler.in_width = data->width;
handle->video.scaler.in_height = data->height;
handle->video.scaler.in_stride = data->pitch;
handle->video.scaler.scaler_type = shrunk ? SCALER_TYPE_BILINEAR : SCALER_TYPE_POINT;
handle->video.scaler.scaler_type = shrunk ?
SCALER_TYPE_BILINEAR : SCALER_TYPE_POINT;
handle->video.scaler.out_width = handle->params.out_width;
handle->video.scaler.out_height = handle->params.out_height;
@ -904,11 +945,13 @@ static void ffmpeg_scale_input(ffmpeg_t *handle, const struct ffemu_video_data *
scaler_ctx_gen_filter(&handle->video.scaler);
}
scaler_ctx_scale(&handle->video.scaler, handle->video.conv_frame->data[0], data->data);
scaler_ctx_scale(&handle->video.scaler,
handle->video.conv_frame->data[0], data->data);
}
}
static bool ffmpeg_push_video_thread(ffmpeg_t *handle, const struct ffemu_video_data *data)
static bool ffmpeg_push_video_thread(ffmpeg_t *handle,
const struct ffemu_video_data *data)
{
if (!data->is_dupe)
ffmpeg_scale_input(handle, data);
@ -957,7 +1000,8 @@ static void planarize_audio(ffmpeg_t *handle)
if (handle->audio.frames_in_buffer > handle->audio.planar_buf_frames)
{
handle->audio.planar_buf = av_realloc(handle->audio.planar_buf,
handle->audio.frames_in_buffer * handle->params.channels * handle->audio.sample_size);
handle->audio.frames_in_buffer * handle->params.channels *
handle->audio.sample_size);
if (!handle->audio.planar_buf)
return;
@ -989,13 +1033,15 @@ static bool encode_audio(ffmpeg_t *handle, AVPacket *pkt, bool dry)
planarize_audio(handle);
int samples_size = av_samples_get_buffer_size(NULL, handle->audio.codec->channels,
int samples_size = av_samples_get_buffer_size(NULL,
handle->audio.codec->channels,
handle->audio.frames_in_buffer,
handle->audio.codec->sample_fmt, 0);
avcodec_fill_audio_frame(frame, handle->audio.codec->channels,
handle->audio.codec->sample_fmt,
handle->audio.is_planar ? (uint8_t*)handle->audio.planar_buf : handle->audio.buffer,
handle->audio.is_planar ? (uint8_t*)handle->audio.planar_buf :
handle->audio.buffer,
samples_size, 0);
int got_packet = 0;
@ -1035,7 +1081,8 @@ static bool encode_audio(ffmpeg_t *handle, AVPacket *pkt, bool dry)
return true;
}
static void ffmpeg_audio_resample(ffmpeg_t *handle, struct ffemu_audio_data *data)
static void ffmpeg_audio_resample(ffmpeg_t *handle,
struct ffemu_audio_data *data)
{
if (!handle->audio.use_float && !handle->audio.resampler)
return;
@ -1049,15 +1096,17 @@ static void ffmpeg_audio_resample(ffmpeg_t *handle, struct ffemu_audio_data *dat
handle->audio.float_conv_frames = data->frames;
// To make sure we don't accidentially overflow.
/* To make sure we don't accidentially overflow. */
handle->audio.resample_out_frames = data->frames * handle->audio.ratio + 16;
handle->audio.resample_out = (float*)av_realloc(handle->audio.resample_out,
handle->audio.resample_out_frames * handle->params.channels * sizeof(float));
handle->audio.resample_out_frames *
handle->params.channels * sizeof(float));
if (!handle->audio.resample_out)
return;
handle->audio.fixed_conv_frames = max(handle->audio.resample_out_frames, handle->audio.float_conv_frames);
handle->audio.fixed_conv_frames = max(handle->audio.resample_out_frames,
handle->audio.float_conv_frames);
handle->audio.fixed_conv = (int16_t*)av_realloc(handle->audio.fixed_conv,
handle->audio.fixed_conv_frames * handle->params.channels * sizeof(int16_t));
if (!handle->audio.fixed_conv)
@ -1073,27 +1122,30 @@ static void ffmpeg_audio_resample(ffmpeg_t *handle, struct ffemu_audio_data *dat
if (handle->audio.resampler)
{
// It's always two channels ...
/* It's always two channels ... */
struct resampler_data info = {0};
info.data_in = (const float*)data->data;
info.data_out = handle->audio.resample_out;
info.input_frames = data->frames;
info.ratio = handle->audio.ratio;
rarch_resampler_process(handle->audio.resampler, handle->audio.resampler_data, &info);
rarch_resampler_process(handle->audio.resampler,
handle->audio.resampler_data, &info);
data->data = handle->audio.resample_out;
data->frames = info.output_frames;
if (!handle->audio.use_float)
{
audio_convert_float_to_s16(handle->audio.fixed_conv, handle->audio.resample_out,
audio_convert_float_to_s16(handle->audio.fixed_conv,
handle->audio.resample_out,
data->frames * handle->params.channels);
data->data = handle->audio.fixed_conv;
}
}
}
static bool ffmpeg_push_audio_thread(ffmpeg_t *handle, struct ffemu_audio_data *data, bool require_block)
static bool ffmpeg_push_audio_thread(ffmpeg_t *handle,
struct ffemu_audio_data *data, bool require_block)
{
ffmpeg_audio_resample(handle, data);
@ -1135,7 +1187,8 @@ static bool ffmpeg_push_audio_thread(ffmpeg_t *handle, struct ffemu_audio_data *
return true;
}
static void ffmpeg_flush_audio(ffmpeg_t *handle, void *audio_buf, size_t audio_buf_size)
static void ffmpeg_flush_audio(ffmpeg_t *handle, void *audio_buf,
size_t audio_buf_size)
{
size_t avail = fifo_read_avail(handle->audio_fifo);
if (avail)
@ -1175,7 +1228,7 @@ static void ffmpeg_flush_buffers(ffmpeg_t *handle)
size_t audio_buf_size = handle->config.audio_enable ? (handle->audio.codec->frame_size * handle->params.channels * sizeof(int16_t)) : 0;
void *audio_buf = audio_buf_size ? av_malloc(audio_buf_size) : NULL;
// Try pushing data in an interleaving pattern to ease the work of the muxer a bit.
/* Try pushing data in an interleaving pattern to ease the work of the muxer a bit. */
bool did_work;
do
{
@ -1208,11 +1261,11 @@ static void ffmpeg_flush_buffers(ffmpeg_t *handle)
}
} while (did_work);
// Flush out last audio.
/* Flush out last audio. */
if (handle->config.audio_enable)
ffmpeg_flush_audio(handle, audio_buf, audio_buf_size);
// Flush out last video.
/* Flush out last video. */
ffmpeg_flush_video(handle);
av_free(video_buf);
@ -1228,12 +1281,12 @@ static bool ffmpeg_finalize(void *data)
deinit_thread(handle);
// Flush out data still in buffers (internal, and FFmpeg internal).
/* Flush out data still in buffers (internal, and FFmpeg internal). */
ffmpeg_flush_buffers(handle);
deinit_thread_buf(handle);
// Write final data.
/* Write final data. */
av_write_trailer(handle->muxer.ctx);
return true;
@ -1243,7 +1296,7 @@ static void ffmpeg_thread(void *data)
{
ffmpeg_t *ff = (ffmpeg_t*)data;
// For some reason, FFmpeg has a tendency to crash if we don't overallocate a bit. :s
/* For some reason, FFmpeg has a tendency to crash if we don't overallocate a bit. */
void *video_buf = av_malloc(2 * ff->params.fb_width * ff->params.fb_height * ff->video.pix_size);
assert(video_buf);

View File

@ -54,12 +54,15 @@
#include "msvc/msvc_compat.h"
#endif
// To avoid continous switching if we hold the button down, we require that the button must go from pressed,
// unpressed back to pressed to be able to toggle between then.
/* To avoid continous switching if we hold the button down, we require
* that the button must go from pressed to unpressed back to pressed
* to be able to toggle between then.
*/
static void check_fast_forward_button(void)
{
bool new_button_state = input_key_pressed_func(RARCH_FAST_FORWARD_KEY);
bool new_hold_button_state = input_key_pressed_func(RARCH_FAST_FORWARD_HOLD_KEY);
bool new_hold_button_state =
input_key_pressed_func(RARCH_FAST_FORWARD_HOLD_KEY);
static bool old_button_state = false;
static bool old_hold_button_state = false;
@ -107,7 +110,7 @@ static bool take_screenshot_viewport(void)
screenshot_dir = screenshot_path;
}
// Data read from viewport is in bottom-up order, suitable for BMP.
/* Data read from viewport is in bottom-up order, suitable for BMP. */
if (!screenshot_dump(screenshot_dir, buffer, vp.width, vp.height,
vp.width * 3, true))
goto done;
@ -131,12 +134,14 @@ static bool take_screenshot_raw(void)
if (!*g_settings.screenshot_directory)
{
fill_pathname_basedir(screenshot_path, g_extern.basename, sizeof(screenshot_path));
fill_pathname_basedir(screenshot_path, g_extern.basename,
sizeof(screenshot_path));
screenshot_dir = screenshot_path;
}
// Negative pitch is needed as screenshot takes bottom-up,
// but we use top-down.
/* Negative pitch is needed as screenshot takes bottom-up,
* but we use top-down.
*/
return screenshot_dump(screenshot_dir,
(const uint8_t*)data + (height - 1) * pitch,
width, height, -pitch, false);
@ -148,7 +153,8 @@ static void take_screenshot(void)
bool ret = false;
const char *msg = NULL;
if ((!*g_settings.screenshot_directory) && (!*g_extern.basename)) // No way to infer screenshot directory.
/* No way to infer screenshot directory. */
if ((!*g_settings.screenshot_directory) && (!*g_extern.basename))
return;
viewport_read = (g_settings.video.gpu_screenshot ||
@ -156,13 +162,13 @@ static void take_screenshot(void)
driver.video->read_viewport &&
driver.video->viewport_info;
// Clear out message queue to avoid OSD fonts to appear on screenshot.
/* Clear out message queue to avoid OSD fonts to appear on screenshot. */
msg_queue_clear(g_extern.msg_queue);
if (viewport_read)
{
#ifdef HAVE_MENU
// Avoid taking screenshot of GUI overlays.
/* Avoid taking screenshot of GUI overlays. */
if (driver.video_poke && driver.video_poke->set_texture_enable)
driver.video_poke->set_texture_enable(driver.video_data, false, false);
#endif
@ -224,6 +230,7 @@ static void deinit_gpu_recording(void)
static void init_recording(void)
{
struct ffemu_params params = {0};
const struct retro_system_av_info *info = {0};
if (!g_extern.recording_enable)
return;
@ -234,15 +241,18 @@ static void init_recording(void)
return;
}
if (!g_settings.video.gpu_record && g_extern.system.hw_render_callback.context_type)
if (!g_settings.video.gpu_record
&& g_extern.system.hw_render_callback.context_type)
{
RARCH_WARN("Libretro core is hardware rendered. Must use post-shaded recording as well.\n");
return;
}
RARCH_LOG("Custom timing given: FPS: %.4f, Sample rate: %.4f\n", (float)g_extern.system.av_info.timing.fps, (float)g_extern.system.av_info.timing.sample_rate);
RARCH_LOG("Custom timing given: FPS: %.4f, Sample rate: %.4f\n",
(float)g_extern.system.av_info.timing.fps,
(float)g_extern.system.av_info.timing.sample_rate);
const struct retro_system_av_info *info = (const struct retro_system_av_info*)&g_extern.system.av_info;
info = (const struct retro_system_av_info*)&g_extern.system.av_info;
params.out_width = info->geometry.base_width;
params.out_height = info->geometry.base_height;
params.fb_width = info->geometry.max_width;
@ -251,7 +261,8 @@ static void init_recording(void)
params.filename = g_extern.record_path;
params.fps = g_extern.system.av_info.timing.fps;
params.samplerate = g_extern.system.av_info.timing.sample_rate;
params.pix_fmt = g_extern.system.pix_fmt == RETRO_PIXEL_FORMAT_XRGB8888 ? FFEMU_PIX_ARGB8888 : FFEMU_PIX_RGB565;
params.pix_fmt = (g_extern.system.pix_fmt == RETRO_PIXEL_FORMAT_XRGB8888) ?
FFEMU_PIX_ARGB8888 : FFEMU_PIX_RGB565;
params.config = *g_extern.record_config ? g_extern.record_config : NULL;
if (g_settings.video.gpu_record && driver.video->read_viewport)
@ -309,7 +320,7 @@ static void init_recording(void)
unsigned max_width = 0;
unsigned max_height = 0;
params.pix_fmt = g_extern.filter.out_rgb32 ? FFEMU_PIX_ARGB8888 : FFEMU_PIX_RGB565;
params.pix_fmt = (g_extern.filter.out_rgb32) ? FFEMU_PIX_ARGB8888 : FFEMU_PIX_RGB565;
rarch_softfilter_get_max_output_size(g_extern.filter.filter, &max_width, &max_height);
params.fb_width = next_pow2(max_width);
@ -346,7 +357,8 @@ static void deinit_recording(void)
deinit_gpu_recording();
}
static void recording_dump_frame(const void *data, unsigned width, unsigned height, size_t pitch)
static void recording_dump_frame(const void *data, unsigned width,
unsigned height, size_t pitch)
{
struct ffemu_video_data ffemu_data = {0};
@ -371,7 +383,7 @@ static void recording_dump_frame(const void *data, unsigned width, unsigned heig
return;
}
// User has resized. We kinda have a problem now.
/* User has resized. We kinda have a problem now. */
if (vp.width != g_extern.record_gpu_width || vp.height != g_extern.record_gpu_height)
{
static const char msg[] = "Recording terminated due to resize.";
@ -383,11 +395,13 @@ static void recording_dump_frame(const void *data, unsigned width, unsigned heig
return;
}
// Big bottleneck.
// Since we might need to do read-backs asynchronously, it might take 3-4 times
// before this returns true ...
/* Big bottleneck.
* Since we might need to do read-backs asynchronously,
* it might take 3-4 times before this returns true ...
*/
if (driver.video && driver.video->read_viewport)
if (!driver.video->read_viewport(driver.video_data, g_extern.record_gpu_buffer))
if (!driver.video->read_viewport(driver.video_data,
g_extern.record_gpu_buffer))
return;
ffemu_data.pitch = g_extern.record_gpu_width * 3;
@ -405,7 +419,8 @@ static void recording_dump_frame(const void *data, unsigned width, unsigned heig
g_extern.rec_driver->push_video(g_extern.rec, &ffemu_data);
}
static void video_frame(const void *data, unsigned width, unsigned height, size_t pitch)
static void video_frame(const void *data, unsigned width,
unsigned height, size_t pitch)
{
const char *msg = NULL;
@ -417,7 +432,8 @@ static void video_frame(const void *data, unsigned width, unsigned height, size_
g_extern.frame_cache.height = height;
g_extern.frame_cache.pitch = pitch;
if (g_extern.system.pix_fmt == RETRO_PIXEL_FORMAT_0RGB1555 && data && data != RETRO_HW_FRAME_BUFFER_VALID)
if (g_extern.system.pix_fmt == RETRO_PIXEL_FORMAT_0RGB1555 &&
data && data != RETRO_HW_FRAME_BUFFER_VALID)
{
RARCH_PERFORMANCE_INIT(video_frame_conv);
RARCH_PERFORMANCE_START(video_frame_conv);
@ -434,9 +450,14 @@ static void video_frame(const void *data, unsigned width, unsigned height, size_
RARCH_PERFORMANCE_STOP(video_frame_conv);
}
// Slightly messy code,
// but we really need to do processing before blocking on VSync for best possible scheduling.
if (g_extern.rec && (!g_extern.filter.filter || !g_settings.video.post_filter_record || !data || g_extern.record_gpu_buffer))
/* Slightly messy code,
* but we really need to do processing before blocking on VSync
* for best possible scheduling.
*/
if (g_extern.rec && (!g_extern.filter.filter
|| !g_settings.video.post_filter_record || !data
|| g_extern.record_gpu_buffer)
)
recording_dump_frame(data, width, height, pitch);
msg = msg_queue_pull(g_extern.msg_queue);
@ -484,9 +505,10 @@ void rarch_render_cached_frame(void)
if (frame == RETRO_HW_FRAME_BUFFER_VALID)
frame = NULL; /* Dupe */
// Not 100% safe, since the library might have
// freed the memory, but no known implementations do this :D
// It would be really stupid at any rate ...
/* Not 100% safe, since the library might have
* freed the memory, but no known implementations do this.
* It would be really stupid at any rate ...
*/
video_frame(frame,
g_extern.frame_cache.width,
g_extern.frame_cache.height,
@ -649,7 +671,8 @@ static inline void input_poll_overlay(void)
for (j = 0; j < ARRAY_SIZE(driver.overlay_state.keys); j++)
driver.overlay_state.keys[j] |= polled_data.keys[j];
// Fingers pressed later take prio and matched up with overlay poll priorities.
/* Fingers pressed later take prio and matched up
* with overlay poll priorities. */
for (j = 0; j < 4; j++)
if (polled_data.analog[j])
driver.overlay_state.analog[j] = polled_data.analog[j];
@ -665,7 +688,8 @@ static inline void input_poll_overlay(void)
OVERLAY_GET_KEY(&driver.overlay_state, RETROK_RALT)) ? RETROKMOD_ALT : 0;
key_mod |= (OVERLAY_GET_KEY(&driver.overlay_state, RETROK_LMETA) ||
OVERLAY_GET_KEY(&driver.overlay_state, RETROK_RMETA)) ? RETROKMOD_META : 0;
// CAPSLOCK SCROLLOCK NUMLOCK
/* CAPSLOCK SCROLLOCK NUMLOCK */
for (i = 0; i < ARRAY_SIZE(driver.overlay_state.keys); i++)
{
if (driver.overlay_state.keys[i] != old_key_state.keys[i])
@ -679,7 +703,7 @@ static inline void input_poll_overlay(void)
}
}
// Map "analog" buttons to analog axes like regular input drivers do.
/* Map "analog" buttons to analog axes like regular input drivers do. */
for (j = 0; j < 4; j++)
{
if (!driver.overlay_state.analog[j])
@ -691,7 +715,8 @@ static inline void input_poll_overlay(void)
}
}
// Check for analog_dpad_mode. Map analogs to d-pad buttons when configured.
/* Check for analog_dpad_mode.
* Map analogs to d-pad buttons when configured. */
switch (g_settings.input.analog_dpad_mode[0])
{
case ANALOG_DPAD_LSTICK:
@ -735,9 +760,10 @@ void rarch_input_poll(void)
#endif
}
// Turbo scheme: If turbo button is held, all buttons pressed except for D-pad will go into
// a turbo mode. Until the button is released again, the input state will be modulated by a periodic pulse defined
// by the configured duty cycle.
/* Turbo scheme: If turbo button is held, all buttons pressed except
* for D-pad will go into a turbo mode. Until the button is
* released again, the input state will be modulated by a periodic pulse
* defined by the configured duty cycle. */
static bool input_apply_turbo(unsigned port, unsigned id, bool res)
{
if (res && g_extern.turbo_frame_enable[port])
@ -750,7 +776,8 @@ static bool input_apply_turbo(unsigned port, unsigned id, bool res)
return res;
}
static int16_t input_state(unsigned port, unsigned device, unsigned index, unsigned id)
static int16_t input_state(unsigned port, unsigned device,
unsigned index, unsigned id)
{
int16_t res = 0;
@ -793,7 +820,7 @@ static int16_t input_state(unsigned port, unsigned device, unsigned index, unsig
}
#endif
// Don't allow turbo for D-pad.
/* Don't allow turbo for D-pad. */
if (device == RETRO_DEVICE_JOYPAD && (id < RETRO_DEVICE_ID_JOYPAD_UP || id > RETRO_DEVICE_ID_JOYPAD_RIGHT))
res = input_apply_turbo(port, id, res);
@ -959,7 +986,7 @@ static void set_special_paths(char **argv, unsigned num_content)
unsigned i;
union string_list_elem_attr attr;
// First content file is the significant one.
/* First content file is the significant one. */
set_basename(argv[0]);
g_extern.subsystem_fullpaths = string_list_new();
@ -970,22 +997,29 @@ static void set_special_paths(char **argv, unsigned num_content)
for (i = 0; i < num_content; i++)
string_list_append(g_extern.subsystem_fullpaths, argv[i], attr);
// We defer SRAM path updates until we can resolve it.
// It is more complicated for special content types.
/* We defer SRAM path updates until we can resolve it.
* It is more complicated for special content types.
*/
if (!g_extern.has_set_state_path)
fill_pathname_noext(g_extern.savestate_name, g_extern.basename, ".state", sizeof(g_extern.savestate_name));
fill_pathname_noext(g_extern.savestate_name, g_extern.basename,
".state", sizeof(g_extern.savestate_name));
if (path_is_directory(g_extern.savestate_name))
{
fill_pathname_dir(g_extern.savestate_name, g_extern.basename, ".state", sizeof(g_extern.savestate_name));
RARCH_LOG("Redirecting save state to \"%s\".\n", g_extern.savestate_name);
fill_pathname_dir(g_extern.savestate_name, g_extern.basename,
".state", sizeof(g_extern.savestate_name));
RARCH_LOG("Redirecting save state to \"%s\".\n",
g_extern.savestate_name);
}
// If this is already set,
// do not overwrite it as this was initialized before in a menu or otherwise.
/* If this is already set,
* do not overwrite it as this was initialized before in
* a menu or otherwise.
*/
if (!*g_settings.system_directory)
fill_pathname_basedir(g_settings.system_directory, argv[0], sizeof(g_settings.system_directory));
fill_pathname_basedir(g_settings.system_directory, argv[0],
sizeof(g_settings.system_directory));
}
static void set_paths(const char *path)
@ -993,25 +1027,30 @@ static void set_paths(const char *path)
set_basename(path);
if (!g_extern.has_set_save_path)
fill_pathname_noext(g_extern.savefile_name, g_extern.basename, ".srm", sizeof(g_extern.savefile_name));
fill_pathname_noext(g_extern.savefile_name, g_extern.basename,
".srm", sizeof(g_extern.savefile_name));
if (!g_extern.has_set_state_path)
fill_pathname_noext(g_extern.savestate_name, g_extern.basename, ".state", sizeof(g_extern.savestate_name));
fill_pathname_noext(g_extern.savestate_name, g_extern.basename,
".state", sizeof(g_extern.savestate_name));
if (path_is_directory(g_extern.savefile_name))
{
fill_pathname_dir(g_extern.savefile_name, g_extern.basename, ".srm", sizeof(g_extern.savefile_name));
fill_pathname_dir(g_extern.savefile_name, g_extern.basename,
".srm", sizeof(g_extern.savefile_name));
RARCH_LOG("Redirecting save file to \"%s\".\n", g_extern.savefile_name);
}
if (path_is_directory(g_extern.savestate_name))
{
fill_pathname_dir(g_extern.savestate_name, g_extern.basename, ".state", sizeof(g_extern.savestate_name));
fill_pathname_dir(g_extern.savestate_name, g_extern.basename,
".state", sizeof(g_extern.savestate_name));
RARCH_LOG("Redirecting save state to \"%s\".\n", g_extern.savestate_name);
}
// If this is already set,
// do not overwrite it as this was initialized before in a menu or otherwise.
/* If this is already set, do not overwrite it
* as this was initialized before in a menu or otherwise. */
if (!*g_settings.system_directory)
fill_pathname_basedir(g_settings.system_directory, path, sizeof(g_settings.system_directory));
fill_pathname_basedir(g_settings.system_directory, path,
sizeof(g_settings.system_directory));
}
static void parse_input(int argc, char *argv[])
@ -1045,7 +1084,7 @@ static void parse_input(int argc, char *argv[])
return;
}
// Make sure we can call parse_input several times ...
/* Make sure we can call parse_input several times ... */
optind = 0;
int val = 0;
@ -1372,7 +1411,7 @@ static void parse_input(int argc, char *argv[])
else
g_extern.libretro_no_content = true;
// Copy SRM/state dirs used, so they can be reused on reentrancy.
/* Copy SRM/state dirs used, so they can be reused on reentrancy. */
if (g_extern.has_set_save_path && path_is_directory(g_extern.savefile_name))
strlcpy(g_extern.savefile_dir, g_extern.savefile_name, sizeof(g_extern.savefile_dir));
if (g_extern.has_set_state_path && path_is_directory(g_extern.savestate_name))
@ -1397,12 +1436,16 @@ static void init_controllers(void)
if (!ident)
{
// If we're trying to connect a completely unknown device, revert back to JOYPAD.
/* If we're trying to connect a completely unknown device,
* revert back to JOYPAD. */
if (device != RETRO_DEVICE_JOYPAD && device != RETRO_DEVICE_NONE)
{
/* Do not fix g_settings.input.libretro_device[i],
* because any use of dummy core will reset this,
* which is not a good idea.
*/
RARCH_WARN("Input device ID %u is unknown to this libretro implementation. Using RETRO_DEVICE_JOYPAD.\n", device);
device = RETRO_DEVICE_JOYPAD;
// Do not fix g_settings.input.libretro_device[i], because any use of dummy core will reset this, which is not a good idea.
}
ident = "Joypad";
}
@ -1414,8 +1457,9 @@ static void init_controllers(void)
}
else if (device != RETRO_DEVICE_JOYPAD)
{
// Some cores do not properly range check port argument.
// This is broken behavior ofc, but avoid breaking cores needlessly.
/* Some cores do not properly range check port argument.
* This is broken behavior ofc, but avoid breaking cores needlessly.
*/
RARCH_LOG("Connecting %s (ID: %u) to port %u.\n", ident, device, i + 1);
pretro_set_controller_port_device(i, device);
}
@ -1430,7 +1474,8 @@ static inline bool load_save_files(void)
return false;
for (i = 0; i < g_extern.savefiles->size; i++)
load_ram_file(g_extern.savefiles->elems[i].data, g_extern.savefiles->elems[i].attr.i);
load_ram_file(g_extern.savefiles->elems[i].data,
g_extern.savefiles->elems[i].attr.i);
return true;
}
@ -1513,8 +1558,11 @@ static void init_rewind(void)
return;
}
RARCH_LOG("Initializing rewind buffer with size: %u MB\n", (unsigned)(g_settings.rewind_buffer_size / 1000000));
g_extern.state_manager = state_manager_new(g_extern.state_size, g_settings.rewind_buffer_size);
RARCH_LOG("Initializing rewind buffer with size: %u MB\n",
(unsigned)(g_settings.rewind_buffer_size / 1000000));
g_extern.state_manager = state_manager_new(g_extern.state_size,
g_settings.rewind_buffer_size);
if (!g_extern.state_manager)
RARCH_WARN("Failed to initialize rewind buffer. Rewinding will be disabled.\n");
@ -1746,8 +1794,12 @@ static void set_savestate_auto_index(void)
if (!g_settings.savestate_auto_index)
return;
// Find the file in the same directory as g_extern.savestate_name with the largest numeral suffix.
// E.g. /foo/path/content.state, will try to find /foo/path/content.state%d, where %d is the largest number available.
/* Find the file in the same directory as g_extern.savestate_name
* with the largest numeral suffix.
*
* E.g. /foo/path/content.state, will try to find
* /foo/path/content.state%d, where %d is the largest number available.
*/
fill_pathname_basedir(state_dir, g_extern.savestate_name, sizeof(state_dir));
fill_pathname_base(state_base, g_extern.savestate_name, sizeof(state_base));
@ -1792,14 +1844,14 @@ static void fill_pathnames(void)
g_extern.savefiles = string_list_new();
rarch_assert(g_extern.savefiles);
// For subsystems, we know exactly which RAM types are supported.
/* For subsystems, we know exactly which RAM types are supported. */
if (*g_extern.subsystem)
{
unsigned i, j;
const struct retro_subsystem_info *info =
(const struct retro_subsystem_info*)libretro_find_subsystem_info(g_extern.system.special, g_extern.system.num_special, g_extern.subsystem);
// We'll handle this error gracefully later.
/* We'll handle this error gracefully later. */
unsigned num_content = min(info ? info->num_roms : 0, g_extern.subsystem_fullpaths ? g_extern.subsystem_fullpaths->size : 0);
bool use_sram_dir = path_is_directory(g_extern.savefile_name);
@ -1816,7 +1868,7 @@ static void fill_pathnames(void)
if (use_sram_dir)
{
// Redirect content fullpath to save directory.
/* Redirect content fullpath to save directory. */
strlcpy(path, g_extern.savefile_name, sizeof(path));
fill_pathname_dir(path, g_extern.subsystem_fullpaths->elems[i].data, ext,
sizeof(path));
@ -1832,12 +1884,14 @@ static void fill_pathnames(void)
}
}
// Let other relevant paths be inferred from the main SRAM location.
/* Let other relevant paths be inferred from the main SRAM location. */
if (!g_extern.has_set_save_path)
fill_pathname_noext(g_extern.savefile_name, g_extern.basename, ".srm", sizeof(g_extern.savefile_name));
fill_pathname_noext(g_extern.savefile_name, g_extern.basename, ".srm",
sizeof(g_extern.savefile_name));
if (path_is_directory(g_extern.savefile_name))
{
fill_pathname_dir(g_extern.savefile_name, g_extern.basename, ".srm", sizeof(g_extern.savefile_name));
fill_pathname_dir(g_extern.savefile_name, g_extern.basename, ".srm",
sizeof(g_extern.savefile_name));
RARCH_LOG("Redirecting save file to \"%s\".\n", g_extern.savefile_name);
}
}
@ -1849,23 +1903,27 @@ static void fill_pathnames(void)
attr.i = RETRO_MEMORY_SAVE_RAM;
string_list_append(g_extern.savefiles, g_extern.savefile_name, attr);
// Infer .rtc save path from save ram path.
/* Infer .rtc save path from save ram path. */
attr.i = RETRO_MEMORY_RTC;
fill_pathname(savefile_name_rtc,
g_extern.savefile_name, ".rtc", sizeof(savefile_name_rtc));
string_list_append(g_extern.savefiles, savefile_name_rtc, attr);
}
fill_pathname(g_extern.bsv.movie_path, g_extern.savefile_name, "", sizeof(g_extern.bsv.movie_path));
fill_pathname(g_extern.bsv.movie_path, g_extern.savefile_name, "",
sizeof(g_extern.bsv.movie_path));
if (*g_extern.basename)
{
if (!*g_extern.ups_name)
fill_pathname_noext(g_extern.ups_name, g_extern.basename, ".ups", sizeof(g_extern.ups_name));
fill_pathname_noext(g_extern.ups_name, g_extern.basename, ".ups",
sizeof(g_extern.ups_name));
if (!*g_extern.bps_name)
fill_pathname_noext(g_extern.bps_name, g_extern.basename, ".bps", sizeof(g_extern.bps_name));
fill_pathname_noext(g_extern.bps_name, g_extern.basename, ".bps",
sizeof(g_extern.bps_name));
if (!*g_extern.ips_name)
fill_pathname_noext(g_extern.ips_name, g_extern.basename, ".ips", sizeof(g_extern.ips_name));
fill_pathname_noext(g_extern.ips_name, g_extern.basename, ".ips",
sizeof(g_extern.ips_name));
}
}
@ -1916,9 +1974,9 @@ static bool save_auto_state(void)
static void rarch_load_state(void)
{
char load_path[PATH_MAX], msg[512];
char load_path[PATH_MAX], msg[PATH_MAX];
// Disallow savestate load when we absolutely cannot change game state.
/* Disallow savestate load when we absolutely cannot change game state. */
if (g_extern.bsv.movie)
return;
@ -1928,23 +1986,29 @@ static void rarch_load_state(void)
#endif
if (g_settings.state_slot > 0)
snprintf(load_path, sizeof(load_path), "%s%d", g_extern.savestate_name, g_settings.state_slot);
snprintf(load_path, sizeof(load_path), "%s%d",
g_extern.savestate_name, g_settings.state_slot);
else if (g_settings.state_slot < 0)
snprintf(load_path, sizeof(load_path), "%s.auto", g_extern.savestate_name);
snprintf(load_path, sizeof(load_path), "%s.auto",
g_extern.savestate_name);
else
snprintf(load_path, sizeof(load_path), "%s", g_extern.savestate_name);
snprintf(load_path, sizeof(load_path), "%s",
g_extern.savestate_name);
if (pretro_serialize_size())
{
if (load_state(load_path))
{
if (g_settings.state_slot < 0)
snprintf(msg, sizeof(msg), "Loaded state from slot #-1 (auto).");
snprintf(msg, sizeof(msg),
"Loaded state from slot #-1 (auto).");
else
snprintf(msg, sizeof(msg), "Loaded state from slot #%d.", g_settings.state_slot);
snprintf(msg, sizeof(msg),
"Loaded state from slot #%d.", g_settings.state_slot);
}
else
snprintf(msg, sizeof(msg), "Failed to load state from \"%s\".", load_path);
snprintf(msg, sizeof(msg),
"Failed to load state from \"%s\".", load_path);
}
else
strlcpy(msg, "Core does not support save states.", sizeof(msg));
@ -1962,23 +2026,29 @@ static void rarch_save_state(void)
g_settings.state_slot++;
if (g_settings.state_slot > 0)
snprintf(save_path, sizeof(save_path), "%s%d", g_extern.savestate_name, g_settings.state_slot);
snprintf(save_path, sizeof(save_path), "%s%d",
g_extern.savestate_name, g_settings.state_slot);
else if (g_settings.state_slot < 0)
snprintf(save_path, sizeof(save_path), "%s.auto", g_extern.savestate_name);
snprintf(save_path, sizeof(save_path), "%s.auto",
g_extern.savestate_name);
else
snprintf(save_path, sizeof(save_path), "%s", g_extern.savestate_name);
snprintf(save_path, sizeof(save_path), "%s",
g_extern.savestate_name);
if (pretro_serialize_size())
{
if (save_state(save_path))
{
if (g_settings.state_slot < 0)
snprintf(msg, sizeof(msg), "Saved state to slot #-1 (auto).");
snprintf(msg, sizeof(msg),
"Saved state to slot #-1 (auto).");
else
snprintf(msg, sizeof(msg), "Saved state to slot #%u.", g_settings.state_slot);
snprintf(msg, sizeof(msg),
"Saved state to slot #%u.", g_settings.state_slot);
}
else
snprintf(msg, sizeof(msg), "Failed to save state to \"%s\".", save_path);
snprintf(msg, sizeof(msg),
"Failed to save state to \"%s\".", save_path);
}
else
strlcpy(msg, "Core does not support save states.", sizeof(msg));
@ -2018,14 +2088,14 @@ static void set_fullscreen(bool fullscreen)
init_drivers();
driver.video_cache_context = false;
// Poll input to avoid possibly stale data to corrupt things.
/* Poll input to avoid possibly stale data to corrupt things. */
if (driver.input)
driver.input->poll(driver.input_data);
}
bool rarch_check_fullscreen(void)
{
// If we go fullscreen we drop all drivers and reinitialize to be safe.
/* If we go fullscreen we drop all drivers and reinitialize to be safe. */
static bool was_pressed = false;
bool pressed = input_key_pressed_func(RARCH_FULLSCREEN_TOGGLE_KEY);
bool toggle = pressed && !was_pressed;
@ -2042,7 +2112,7 @@ bool rarch_check_fullscreen(void)
static void rarch_state_slot_increase(void)
{
char msg[256];
char msg[PATH_MAX];
g_settings.state_slot++;
@ -2059,7 +2129,7 @@ static void rarch_state_slot_increase(void)
static void rarch_state_slot_decrease(void)
{
char msg[256];
char msg[PATH_MAX];
if (g_settings.state_slot > 0)
g_settings.state_slot--;
@ -2098,9 +2168,11 @@ static inline void flush_rewind_audio(void)
if (!g_extern.frame_is_reverse)
return;
// We just rewound. Flush rewind audio buffer.
g_extern.audio_active = audio_flush(g_extern.audio_data.rewind_buf + g_extern.audio_data.rewind_ptr,
g_extern.audio_data.rewind_size - g_extern.audio_data.rewind_ptr) && g_extern.audio_active;
/* We just rewound. Flush rewind audio buffer. */
g_extern.audio_active = audio_flush(g_extern.audio_data.rewind_buf
+ g_extern.audio_data.rewind_ptr,
g_extern.audio_data.rewind_size - g_extern.audio_data.rewind_ptr)
&& g_extern.audio_active;
g_extern.frame_is_reverse = false;
}
@ -2109,7 +2181,7 @@ static inline void setup_rewind_audio(void)
{
unsigned i;
// Push audio ready to be played.
/* Push audio ready to be played. */
g_extern.audio_data.rewind_ptr = g_extern.audio_data.rewind_size;
for (i = 0; i < g_extern.audio_data.data_ptr; i += 2)
@ -2149,20 +2221,23 @@ static void check_rewind(void)
g_extern.frame_is_reverse = true;
setup_rewind_audio();
msg_queue_push(g_extern.msg_queue, "Rewinding.", 0, g_extern.is_paused ? 1 : 30);
msg_queue_push(g_extern.msg_queue, "Rewinding.", 0,
g_extern.is_paused ? 1 : 30);
pretro_unserialize(buf, g_extern.state_size);
if (g_extern.bsv.movie)
bsv_movie_frame_rewind(g_extern.bsv.movie);
}
else
msg_queue_push(g_extern.msg_queue, "Reached end of rewind buffer.", 0, 30);
msg_queue_push(g_extern.msg_queue,
"Reached end of rewind buffer.", 0, 30);
}
else
{
static unsigned cnt = 0;
cnt = (cnt + 1) % (g_settings.rewind_granularity ? g_settings.rewind_granularity : 1); // Avoid possible SIGFPE.
cnt = (cnt + 1) % (g_settings.rewind_granularity ?
g_settings.rewind_granularity : 1); /* Avoid possible SIGFPE. */
if ((cnt == 0) || g_extern.bsv.movie)
{
@ -2192,7 +2267,8 @@ static void check_slowmotion(void)
return;
msg_queue_clear(g_extern.msg_queue);
msg_queue_push(g_extern.msg_queue, g_extern.frame_is_reverse ? "Slow motion rewind." : "Slow motion.", 0, 30);
msg_queue_push(g_extern.msg_queue, g_extern.frame_is_reverse ?
"Slow motion rewind." : "Slow motion.", 0, 30);
}
static void check_movie_record(bool pressed)
@ -2228,7 +2304,8 @@ static void check_movie_record(bool pressed)
g_extern.bsv.movie = bsv_movie_init(path, RARCH_MOVIE_RECORD);
msg_queue_clear(g_extern.msg_queue);
msg_queue_push(g_extern.msg_queue, g_extern.bsv.movie ? msg : "Failed to start movie record.", 1, 180);
msg_queue_push(g_extern.msg_queue, g_extern.bsv.movie ?
msg : "Failed to start movie record.", 1, 180);
if (g_extern.bsv.movie)
RARCH_LOG("Starting movie record to \"%s\".\n", path);
@ -2273,8 +2350,9 @@ static void check_pause(void)
bool has_set_audio_start = false;
bool new_state = input_key_pressed_func(RARCH_PAUSE_TOGGLE);
// FRAMEADVANCE will set us into pause mode.
new_state |= !g_extern.is_paused && input_key_pressed_func(RARCH_FRAMEADVANCE);
/* FRAMEADVANCE will set us into pause mode. */
new_state |= !g_extern.is_paused &&
input_key_pressed_func(RARCH_FRAMEADVANCE);
if (g_settings.pause_nonactive)
focus = driver.video->focus(driver.video_data);
@ -2326,7 +2404,8 @@ static void check_oneshot(void)
g_extern.is_oneshot = (new_state && !old_state);
old_state = new_state;
// Rewind buttons works like FRAMEREWIND when paused. We will one-shot in that case.
/* Rewind buttons works like FRAMEREWIND when paused.
* We will one-shot in that case. */
g_extern.is_oneshot |= new_rewind_state && !old_rewind_state;
old_rewind_state = new_rewind_state;
}
@ -2360,12 +2439,14 @@ static void check_turbo(void)
if (driver.block_libretro_input)
memset(g_extern.turbo_frame_enable, 0, sizeof(g_extern.turbo_frame_enable));
memset(g_extern.turbo_frame_enable, 0,
sizeof(g_extern.turbo_frame_enable));
else
{
for (i = 0; i < MAX_PLAYERS; i++)
g_extern.turbo_frame_enable[i] =
driver.input->input_state(driver.input_data, binds, i, RETRO_DEVICE_JOYPAD, 0, RARCH_TURBO_ENABLE);
driver.input->input_state(driver.input_data, binds, i,
RETRO_DEVICE_JOYPAD, 0, RARCH_TURBO_ENABLE);
}
}
@ -2483,13 +2564,14 @@ void rarch_disk_control_append_image(const char *path)
deinit_autosave();
#endif
// TODO: Need to figure out what to do with subsystems case.
/* TODO: Need to figure out what to do with subsystems case. */
if (!*g_extern.subsystem)
{
// Update paths for our new image.
// If we actually use append_image,
// we assume that we started out in a single disk case,
// and that this way of doing it makes the most sense.
/* Update paths for our new image.
* If we actually use append_image,
* we assume that we started out in a single disk case,
* and that this way of doing it makes the most sense.
*/
set_paths(path);
fill_pathnames();
}
@ -2514,11 +2596,13 @@ void rarch_disk_control_set_eject(bool new_state, bool log)
*msg = '\0';
if (control->set_eject_state(new_state))
snprintf(msg, sizeof(msg), "%s virtual disk tray.", new_state ? "Ejected" : "Closed");
snprintf(msg, sizeof(msg), "%s virtual disk tray.",
new_state ? "Ejected" : "Closed");
else
{
error = true;
snprintf(msg, sizeof(msg), "Failed to %s virtual disk tray.", new_state ? "eject" : "close");
snprintf(msg, sizeof(msg), "Failed to %s virtual disk tray.",
new_state ? "eject" : "close");
}
if (*msg)
@ -2528,7 +2612,7 @@ void rarch_disk_control_set_eject(bool new_state, bool log)
else
RARCH_LOG("%s\n", msg);
// Only noise in menu.
/* Only noise in menu. */
if (log)
{
msg_queue_clear(g_extern.msg_queue);
@ -2555,14 +2639,16 @@ void rarch_disk_control_set_index(unsigned next_index)
if (control->set_image_index(next_index))
{
if (next_index < num_disks)
snprintf(msg, sizeof(msg), "Setting disk %u of %u in tray.", next_index + 1, num_disks);
snprintf(msg, sizeof(msg), "Setting disk %u of %u in tray.",
next_index + 1, num_disks);
else
strlcpy(msg, "Removed disk from tray.", sizeof(msg));
}
else
{
if (next_index < num_disks)
snprintf(msg, sizeof(msg), "Failed to set disk %u of %u.", next_index + 1, num_disks);
snprintf(msg, sizeof(msg), "Failed to set disk %u of %u.",
next_index + 1, num_disks);
else
strlcpy(msg, "Failed to remove disk from tray.", sizeof(msg));
error = true;
@ -2605,8 +2691,9 @@ static void check_disk(void)
unsigned current = control->get_image_index();
if (num_disks && num_disks != UINT_MAX)
{
// Use "no disk" state when index == num_disks.
unsigned next_index = current >= num_disks ? 0 : ((current + 1) % (num_disks + 1));
/* Use "no disk" state when index == num_disks. */
unsigned next_index = current >= num_disks ?
0 : ((current + 1) % (num_disks + 1));
rarch_disk_control_set_index(next_index);
}
else
@ -2640,7 +2727,8 @@ static void check_mute(void)
{
g_extern.audio_data.mute = !g_extern.audio_data.mute;
const char *msg = g_extern.audio_data.mute ? "Audio muted." : "Audio unmuted.";
const char *msg = g_extern.audio_data.mute ?
"Audio muted." : "Audio unmuted.";
msg_queue_clear(g_extern.msg_queue);
msg_queue_push(g_extern.msg_queue, msg, 1, 180);
@ -2709,16 +2797,19 @@ void rarch_check_block_hotkey(void)
static const struct retro_keybind *bind = &g_settings.input.binds[0][RARCH_ENABLE_HOTKEY];
bool use_hotkey_enable, enable_hotkey;
// Don't block the check to RARCH_ENABLE_HOTKEY unless we're really supposed to.
/* Don't block the check to RARCH_ENABLE_HOTKEY
* unless we're really supposed to. */
driver.block_hotkey = driver.block_input;
// If we haven't bound anything to this, always allow hotkeys.
use_hotkey_enable = bind->key != RETROK_UNKNOWN || bind->joykey != NO_BTN || bind->joyaxis != AXIS_NONE;
use_hotkey_enable = bind->key != RETROK_UNKNOWN || bind->joykey != NO_BTN ||
bind->joyaxis != AXIS_NONE;
enable_hotkey = input_key_pressed_func(RARCH_ENABLE_HOTKEY);
driver.block_hotkey = driver.block_input || (use_hotkey_enable && !enable_hotkey);
// If we hold ENABLE_HOTKEY button, block all libretro input to allow hotkeys to be bound to same keys as RetroPad.
/* If we hold ENABLE_HOTKEY button, block all libretro input to allow
* hotkeys to be bound to same keys as RetroPad. */
driver.block_libretro_input = use_hotkey_enable && enable_hotkey;
}
@ -2864,7 +2955,8 @@ void rarch_init_system_info(void)
snprintf(g_extern.title_buf, sizeof(g_extern.title_buf), "RetroArch : %s %s",
info->library_name, info->library_version);
#endif
strlcpy(g_extern.system.valid_extensions, info->valid_extensions ? info->valid_extensions : DEFAULT_EXT,
strlcpy(g_extern.system.valid_extensions, info->valid_extensions ?
info->valid_extensions : DEFAULT_EXT,
sizeof(g_extern.system.valid_extensions));
g_extern.system.block_extract = info->block_extract;
}
@ -2883,8 +2975,9 @@ static void verify_api_version(void)
RARCH_WARN("RetroArch is compiled against a different version of libretro than this libretro implementation.\n");
}
// Make sure we haven't compiled for something we cannot run.
// Ideally, code would get swapped out depending on CPU support, but this will do for now.
/* Make sure we haven't compiled for something we cannot run.
* Ideally, code would get swapped out depending on CPU support, but this will do for now.
*/
static void validate_cpu_features(void)
{
uint64_t cpu = rarch_get_cpu_features();
@ -3033,7 +3126,7 @@ static inline bool check_enter_menu(void)
bool rmenu_toggle = input_key_pressed_func(RARCH_MENU_TOGGLE)
|| (g_extern.libretro_dummy && !old_rmenu_toggle);
// Always go into menu if dummy core is loaded.
/* Always go into menu if dummy core is loaded. */
if (rmenu_toggle && !old_rmenu_toggle)
{
g_extern.lifecycle_state |= (1ULL << MODE_MENU_PREINIT);
@ -3080,7 +3173,9 @@ static inline void limit_frame_time(void)
if (g_settings.fastforward_ratio < 0.0f)
return;
g_extern.frame_limit.minimum_frame_time = (retro_time_t)roundf(1000000.0f / (g_extern.system.av_info.timing.fps * g_settings.fastforward_ratio));
g_extern.frame_limit.minimum_frame_time = (retro_time_t)
roundf(1000000.0f / (g_extern.system.av_info.timing.fps *
g_settings.fastforward_ratio));
retro_time_t current = rarch_get_time_usec();
retro_time_t target = g_extern.frame_limit.last_frame_time + g_extern.frame_limit.minimum_frame_time;
@ -3094,8 +3189,9 @@ static inline void limit_frame_time(void)
g_extern.frame_limit.last_frame_time = rarch_get_time_usec();
}
//TODO - can we refactor command.c to do this? Should be local and not
//stdin or network-based
/*TODO - can we refactor command.c to do this? Should be local and not
* stdin or network-based
*/
void rarch_main_command(unsigned action)
{
@ -3274,16 +3370,16 @@ bool rarch_main_iterate(void)
{
unsigned i;
// SHUTDOWN on consoles should exit RetroArch completely.
/* SHUTDOWN on consoles should exit RetroArch completely. */
if (g_extern.system.shutdown)
return false;
// Time to drop?
/* Time to drop? */
if (input_key_pressed_func(RARCH_QUIT_KEY) || !driver.video->alive(driver.video_data))
return false;
if (check_enter_menu())
return false; // Enter menu, don't exit.
return false; /* Enter menu, don't exit. */
if (g_extern.exec)
{
@ -3291,7 +3387,7 @@ bool rarch_main_iterate(void)
return false;
}
// Checks for stuff like fullscreen, save states, etc.
/* Checks for stuff like fullscreen, save states, etc. */
do_state_checks();
if (g_extern.is_paused && !g_extern.is_oneshot)
@ -3301,7 +3397,7 @@ bool rarch_main_iterate(void)
return true;
}
// Run libretro for one frame.
/* Run libretro for one frame. */
#if defined(HAVE_THREADS)
lock_autosave();
#endif
@ -3317,11 +3413,13 @@ bool rarch_main_iterate(void)
if (g_extern.system.camera_callback.caps)
driver_camera_poll();
// Update binds for analog dpad modes.
/* Update binds for analog dpad modes. */
for (i = 0; i < MAX_PLAYERS; i++)
{
input_push_analog_dpad(g_settings.input.binds[i], g_settings.input.analog_dpad_mode[i]);
input_push_analog_dpad(g_settings.input.autoconf_binds[i], g_settings.input.analog_dpad_mode[i]);
input_push_analog_dpad(g_settings.input.binds[i],
g_settings.input.analog_dpad_mode[i]);
input_push_analog_dpad(g_settings.input.autoconf_binds[i],
g_settings.input.analog_dpad_mode[i]);
}
update_frame_time();

View File

@ -37,7 +37,7 @@ static bool write_header_bmp(FILE *file, unsigned width, unsigned height)
unsigned size = line_size * height + 54;
unsigned size_array = line_size * height;
// Generic BMP stuff.
/* Generic BMP stuff. */
const uint8_t header[] = {
'B', 'M',
(uint8_t)(size >> 0), (uint8_t)(size >> 8), (uint8_t)(size >> 16), (uint8_t)(size >> 24),
@ -123,7 +123,7 @@ static void dump_content(FILE *file, const void *frame,
goto end;
}
if (bgr24) // BGR24 byte order. Can directly copy.
if (bgr24) /* BGR24 byte order. Can directly copy. */
{
for (j = 0; j < height; j++, u.u8 += pitch)
dump_line_bgr(lines[j], u.u8, width);
@ -133,7 +133,7 @@ static void dump_content(FILE *file, const void *frame,
for (j = 0; j < height; j++, u.u8 += pitch)
dump_line_32(lines[j], u.u32, width);
}
else // RGB565
else /* RGB565 */
{
for (j = 0; j < height; j++, u.u8 += pitch)
dump_line_16(lines[j], u.u16, width);
@ -148,7 +148,7 @@ end:
}
#endif
// Take frame bottom-up.
/* Take frame bottom-up. */
bool screenshot_dump(const char *folder, const void *frame,
unsigned width, unsigned height, int pitch, bool bgr24)
{