commit
00ba1646c6
|
@ -685,7 +685,8 @@ endif
|
||||||
|
|
||||||
ifeq ($(TARGET), retroarch_3ds)
|
ifeq ($(TARGET), retroarch_3ds)
|
||||||
OBJ += audio/drivers/ctr_csnd_audio.o \
|
OBJ += audio/drivers/ctr_csnd_audio.o \
|
||||||
audio/drivers/ctr_dsp_audio.o
|
audio/drivers/ctr_dsp_audio.o \
|
||||||
|
audio/drivers/ctr_dsp_thread_audio.o
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifeq ($(HAVE_ALSA), 1)
|
ifeq ($(HAVE_ALSA), 1)
|
||||||
|
|
33
Makefile.ctr
33
Makefile.ctr
|
@ -8,6 +8,7 @@ BUILD_3DSX = 1
|
||||||
BUILD_3DS = 0
|
BUILD_3DS = 0
|
||||||
BUILD_CIA = 1
|
BUILD_CIA = 1
|
||||||
LIBCTRU_NO_DEPRECATION = 1
|
LIBCTRU_NO_DEPRECATION = 1
|
||||||
|
USE_CTRULIB_2 = 0
|
||||||
|
|
||||||
APP_TITLE = RetroArch 3DS
|
APP_TITLE = RetroArch 3DS
|
||||||
APP_DESCRIPTION = RetroArch 3DS
|
APP_DESCRIPTION = RetroArch 3DS
|
||||||
|
@ -35,8 +36,7 @@ OBJ += ctr/exec-3dsx/exec_cia.o \
|
||||||
ctr/exec-3dsx/exec_3dsx.o \
|
ctr/exec-3dsx/exec_3dsx.o \
|
||||||
ctr/exec-3dsx/mini-hb-menu/launch.o \
|
ctr/exec-3dsx/mini-hb-menu/launch.o \
|
||||||
ctr/exec-3dsx/mini-hb-menu/loaders/rosalina.o \
|
ctr/exec-3dsx/mini-hb-menu/loaders/rosalina.o \
|
||||||
ctr/exec-3dsx/mini-hb-menu/loaders/hax2.o \
|
ctr/exec-3dsx/mini-hb-menu/loaders/hax2.o
|
||||||
ctr/exec-3dsx/mini-hb-menu/loaders/ninjhax1.o
|
|
||||||
|
|
||||||
ifeq ($(APP_BIG_TEXT_SECTION), 1)
|
ifeq ($(APP_BIG_TEXT_SECTION), 1)
|
||||||
APP_USE_SVCHAX = 1
|
APP_USE_SVCHAX = 1
|
||||||
|
@ -56,7 +56,8 @@ ifeq ($(GRIFFIN_BUILD), 1)
|
||||||
DEFINES += -DHAVE_PATCH -DHAVE_RWAV
|
DEFINES += -DHAVE_PATCH -DHAVE_RWAV
|
||||||
DEFINES += -DHAVE_SCREENSHOTS
|
DEFINES += -DHAVE_SCREENSHOTS
|
||||||
DEFINES += -DHAVE_REWIND
|
DEFINES += -DHAVE_REWIND
|
||||||
#DEFINES += -DHAVE_SOCKET_LEGACY -DHAVE_THREADS
|
DEFINES += -DHAVE_THREADS
|
||||||
|
#DEFINES += -DHAVE_SOCKET_LEGACY
|
||||||
#-DHAVE_SSL -DHAVE_BUILTINMBEDTLS -DMBEDTLS_SSL_DEBUG_ALL
|
#-DHAVE_SSL -DHAVE_BUILTINMBEDTLS -DMBEDTLS_SSL_DEBUG_ALL
|
||||||
#ssl is currently incompatible with griffin due to use of the "static" flag on repeating functions that will conflict when included in one file
|
#ssl is currently incompatible with griffin due to use of the "static" flag on repeating functions that will conflict when included in one file
|
||||||
else
|
else
|
||||||
|
@ -84,7 +85,7 @@ else
|
||||||
#HAVE_NETWORKING = 1
|
#HAVE_NETWORKING = 1
|
||||||
#HAVE_CHEEVOS = 1
|
#HAVE_CHEEVOS = 1
|
||||||
#HAVE_SOCKET_LEGACY = 1
|
#HAVE_SOCKET_LEGACY = 1
|
||||||
#HAVE_THREADS = 1
|
HAVE_THREADS = 1
|
||||||
#HAVE_SSL = 1
|
#HAVE_SSL = 1
|
||||||
#HAVE_BUILTINMBEDTLS = 1
|
#HAVE_BUILTINMBEDTLS = 1
|
||||||
|
|
||||||
|
@ -104,6 +105,18 @@ ifeq ($(strip $(CTRULIB)),)
|
||||||
CTRULIB = $(DEVKITPRO)/libctru
|
CTRULIB = $(DEVKITPRO)/libctru
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
ifeq ($(strip $(USE_CTRULIB_2)),1)
|
||||||
|
CFLAGS += -DUSE_CTRULIB_2
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifeq ($(strip $(DEVKITTOOLS)),)
|
||||||
|
ifeq ($(strip $(USE_CTRULIB_2)),1)
|
||||||
|
DEVKITTOOLS = $(DEVKITPRO)/tools
|
||||||
|
else
|
||||||
|
DEVKITTOOLS = $(DEVKITARM)
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
|
||||||
APP_TITLE := $(shell echo "$(APP_TITLE)" | cut -c1-128)
|
APP_TITLE := $(shell echo "$(APP_TITLE)" | cut -c1-128)
|
||||||
APP_DESCRIPTION := $(shell echo "$(APP_DESCRIPTION)" | cut -c1-256)
|
APP_DESCRIPTION := $(shell echo "$(APP_DESCRIPTION)" | cut -c1-256)
|
||||||
APP_AUTHOR := $(shell echo "$(APP_AUTHOR)" | cut -c1-128)
|
APP_AUTHOR := $(shell echo "$(APP_AUTHOR)" | cut -c1-128)
|
||||||
|
@ -225,13 +238,13 @@ else
|
||||||
endif
|
endif
|
||||||
|
|
||||||
%.o: %.vsh %.gsh
|
%.o: %.vsh %.gsh
|
||||||
$(DEVKITARM)/bin/picasso $^ -o $*.shbin
|
$(DEVKITTOOLS)/bin/picasso $^ -o $*.shbin
|
||||||
$(DEVKITARM)/bin/bin2s $*.shbin | $(PREFIX)as -o $@
|
$(DEVKITTOOLS)/bin/bin2s $*.shbin | $(PREFIX)as -o $@
|
||||||
rm $*.shbin
|
rm $*.shbin
|
||||||
|
|
||||||
%.o: %.vsh
|
%.o: %.vsh
|
||||||
$(DEVKITARM)/bin/picasso $^ -o $*.shbin
|
$(DEVKITTOOLS)/bin/picasso $^ -o $*.shbin
|
||||||
$(DEVKITARM)/bin/bin2s $*.shbin | $(PREFIX)as -o $@
|
$(DEVKITTOOLS)/bin/bin2s $*.shbin | $(PREFIX)as -o $@
|
||||||
rm $*.shbin
|
rm $*.shbin
|
||||||
|
|
||||||
%.o: %.cpp
|
%.o: %.cpp
|
||||||
|
@ -252,7 +265,7 @@ endif
|
||||||
%.vsh:
|
%.vsh:
|
||||||
|
|
||||||
$(TARGET).smdh: $(APP_ICON)
|
$(TARGET).smdh: $(APP_ICON)
|
||||||
$(DEVKITARM)/bin/smdhtool --create "$(APP_TITLE)" "$(APP_DESCRIPTION)" "$(APP_AUTHOR)" $(APP_ICON) $@
|
$(DEVKITTOOLS)/bin/smdhtool --create "$(APP_TITLE)" "$(APP_DESCRIPTION)" "$(APP_AUTHOR)" $(APP_ICON) $@
|
||||||
|
|
||||||
$(TARGET).3dsx: $(TARGET).elf
|
$(TARGET).3dsx: $(TARGET).elf
|
||||||
ifeq ($(APP_BIG_TEXT_SECTION), 1)
|
ifeq ($(APP_BIG_TEXT_SECTION), 1)
|
||||||
|
@ -260,7 +273,7 @@ ifeq ($(APP_BIG_TEXT_SECTION), 1)
|
||||||
else
|
else
|
||||||
rm -f $(TARGET).xml
|
rm -f $(TARGET).xml
|
||||||
endif
|
endif
|
||||||
$(DEVKITARM)/bin/3dsxtool $< $@ $(_3DSXFLAGS)
|
$(DEVKITTOOLS)/bin/3dsxtool $< $@ $(_3DSXFLAGS)
|
||||||
|
|
||||||
$(TARGET).elf: ctr/3dsx_custom_crt0.o
|
$(TARGET).elf: ctr/3dsx_custom_crt0.o
|
||||||
$(LD) $(LDFLAGS) $(OBJ) $(LIBDIRS) $(LIBS) -o $@
|
$(LD) $(LDFLAGS) $(OBJ) $(LIBDIRS) $(LIBS) -o $@
|
||||||
|
|
|
@ -5,6 +5,7 @@ DEBUG = 0
|
||||||
BUILD_3DSX = 1
|
BUILD_3DSX = 1
|
||||||
BUILD_3DS = 0
|
BUILD_3DS = 0
|
||||||
BUILD_CIA = 1
|
BUILD_CIA = 1
|
||||||
|
USE_CTRULIB_2 = 0
|
||||||
|
|
||||||
APP_TITLE = RetroArch 3DS
|
APP_TITLE = RetroArch 3DS
|
||||||
APP_DESCRIPTION = RetroArch 3DS
|
APP_DESCRIPTION = RetroArch 3DS
|
||||||
|
@ -45,13 +46,24 @@ OBJ += ctr/exec-3dsx/exec_cia.o \
|
||||||
ctr/exec-3dsx/exec_3dsx.o \
|
ctr/exec-3dsx/exec_3dsx.o \
|
||||||
ctr/exec-3dsx/mini-hb-menu/launch.o \
|
ctr/exec-3dsx/mini-hb-menu/launch.o \
|
||||||
ctr/exec-3dsx/mini-hb-menu/loaders/rosalina.o \
|
ctr/exec-3dsx/mini-hb-menu/loaders/rosalina.o \
|
||||||
ctr/exec-3dsx/mini-hb-menu/loaders/hax2.o \
|
ctr/exec-3dsx/mini-hb-menu/loaders/hax2.o
|
||||||
ctr/exec-3dsx/mini-hb-menu/loaders/ninjhax1.o
|
|
||||||
|
|
||||||
ifeq ($(strip $(DEVKITPRO)),)
|
ifeq ($(strip $(DEVKITPRO)),)
|
||||||
$(error "Please set DEVKITPRO in your environment. export DEVKITPRO=<path to>devkitpro")
|
$(error "Please set DEVKITPRO in your environment. export DEVKITPRO=<path to>devkitpro")
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
ifeq ($(strip $(USE_CTRULIB_2)),1)
|
||||||
|
CFLAGS += -DUSE_CTRULIB_2
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifeq ($(strip $(DEVKITTOOLS)),)
|
||||||
|
ifeq ($(strip $(USE_CTRULIB_2)),1)
|
||||||
|
DEVKITTOOLS = $(DEVKITPRO)/tools
|
||||||
|
else
|
||||||
|
DEVKITTOOLS = $(DEVKITARM)
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
|
||||||
ifeq ($(strip $(CTRULIB)),)
|
ifeq ($(strip $(CTRULIB)),)
|
||||||
CTRULIB = $(DEVKITPRO)/libctru
|
CTRULIB = $(DEVKITPRO)/libctru
|
||||||
endif
|
endif
|
||||||
|
@ -153,13 +165,13 @@ else
|
||||||
endif
|
endif
|
||||||
|
|
||||||
%.o: %.vsh %.gsh
|
%.o: %.vsh %.gsh
|
||||||
$(DEVKITARM)/bin/picasso $^ -o $*.shbin
|
$(DEVKITTOOLS)/bin/picasso $^ -o $*.shbin
|
||||||
$(DEVKITARM)/bin/bin2s $*.shbin | $(PREFIX)as -o $@
|
$(DEVKITTOOLS)/bin/bin2s $*.shbin | $(PREFIX)as -o $@
|
||||||
rm $*.shbin
|
rm $*.shbin
|
||||||
|
|
||||||
%.o: %.vsh
|
%.o: %.vsh
|
||||||
$(DEVKITARM)/bin/picasso $^ -o $*.shbin
|
$(DEVKITTOOLS)/bin/picasso $^ -o $*.shbin
|
||||||
$(DEVKITARM)/bin/bin2s $*.shbin | $(PREFIX)as -o $@
|
$(DEVKITTOOLS)/bin/bin2s $*.shbin | $(PREFIX)as -o $@
|
||||||
rm $*.shbin
|
rm $*.shbin
|
||||||
|
|
||||||
%.o: %.cpp
|
%.o: %.cpp
|
||||||
|
@ -180,7 +192,7 @@ endif
|
||||||
%.vsh:
|
%.vsh:
|
||||||
|
|
||||||
$(TARGET).smdh: $(APP_ICON)
|
$(TARGET).smdh: $(APP_ICON)
|
||||||
$(DEVKITARM)/bin/smdhtool --create "$(APP_TITLE)" "$(APP_DESCRIPTION)" "$(APP_AUTHOR)" $(APP_ICON) $@
|
$(DEVKITTOOLS)/bin/smdhtool --create "$(APP_TITLE)" "$(APP_DESCRIPTION)" "$(APP_AUTHOR)" $(APP_ICON) $@
|
||||||
|
|
||||||
$(TARGET).3dsx: $(TARGET).elf
|
$(TARGET).3dsx: $(TARGET).elf
|
||||||
ifeq ($(APP_BIG_TEXT_SECTION), 1)
|
ifeq ($(APP_BIG_TEXT_SECTION), 1)
|
||||||
|
@ -188,7 +200,7 @@ ifeq ($(APP_BIG_TEXT_SECTION), 1)
|
||||||
else
|
else
|
||||||
rm -f $(TARGET).xml
|
rm -f $(TARGET).xml
|
||||||
endif
|
endif
|
||||||
$(DEVKITARM)/bin/3dsxtool $< $@ $(_3DSXFLAGS)
|
$(DEVKITTOOLS)/bin/3dsxtool $< $@ $(_3DSXFLAGS)
|
||||||
|
|
||||||
$(TARGET).elf: ctr/3dsx_custom_crt0.o
|
$(TARGET).elf: ctr/3dsx_custom_crt0.o
|
||||||
$(LD) $(LDFLAGS) $(OBJ) $(LIBDIRS) $(LIBS) -o $@
|
$(LD) $(LDFLAGS) $(OBJ) $(LIBDIRS) $(LIBS) -o $@
|
||||||
|
|
|
@ -107,6 +107,15 @@ static ssize_t ctr_dsp_audio_write(void *data, const void *buf, size_t size)
|
||||||
{
|
{
|
||||||
do{
|
do{
|
||||||
svcSleepThread(100000);
|
svcSleepThread(100000);
|
||||||
|
|
||||||
|
/* Run aptMainLoop to update APT state if DSP state
|
||||||
|
* changed, this prevents a hang on sleep. */
|
||||||
|
if(!aptMainLoop())
|
||||||
|
{
|
||||||
|
command_event(CMD_EVENT_QUIT, NULL);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
sample_pos = ndspChnGetSamplePos(ctr->channel);
|
sample_pos = ndspChnGetSamplePos(ctr->channel);
|
||||||
}while (((sample_pos - (ctr->pos + (size >>2))) & CTR_DSP_AUDIO_COUNT_MASK) > (CTR_DSP_AUDIO_COUNT >> 1)
|
}while (((sample_pos - (ctr->pos + (size >>2))) & CTR_DSP_AUDIO_COUNT_MASK) > (CTR_DSP_AUDIO_COUNT >> 1)
|
||||||
|| (((ctr->pos - (CTR_DSP_AUDIO_COUNT >> 4) - sample_pos) & CTR_DSP_AUDIO_COUNT_MASK) > (CTR_DSP_AUDIO_COUNT >> 1)));
|
|| (((ctr->pos - (CTR_DSP_AUDIO_COUNT >> 4) - sample_pos) & CTR_DSP_AUDIO_COUNT_MASK) > (CTR_DSP_AUDIO_COUNT >> 1)));
|
||||||
|
|
|
@ -0,0 +1,339 @@
|
||||||
|
/* RetroArch - A frontend for libretro.
|
||||||
|
* Copyright (C) 2020 - Justin Weiss
|
||||||
|
*
|
||||||
|
* RetroArch is free software: you can redistribute it and/or modify it under the terms
|
||||||
|
* of the GNU General Public License as published by the Free Software Found-
|
||||||
|
* ation, either version 3 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||||
|
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||||
|
* PURPOSE. See the GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along with RetroArch.
|
||||||
|
* If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <3ds.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <malloc.h>
|
||||||
|
#include <queues/fifo_queue.h>
|
||||||
|
#include <rthreads/rthreads.h>
|
||||||
|
|
||||||
|
#include "../../retroarch.h"
|
||||||
|
#include "../../ctr/ctr_debug.h"
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
fifo_buffer_t* fifo;
|
||||||
|
size_t fifo_size;
|
||||||
|
|
||||||
|
slock_t* fifo_lock;
|
||||||
|
scond_t* fifo_avail;
|
||||||
|
scond_t* fifo_done;
|
||||||
|
sthread_t* thread;
|
||||||
|
|
||||||
|
volatile bool running;
|
||||||
|
|
||||||
|
bool nonblocking;
|
||||||
|
bool playing;
|
||||||
|
retro_time_t frame_time;
|
||||||
|
int channel;
|
||||||
|
ndspWaveBuf dsp_buf;
|
||||||
|
|
||||||
|
uint32_t pos;
|
||||||
|
} ctr_dsp_thread_audio_t;
|
||||||
|
|
||||||
|
// PCM16 stereo
|
||||||
|
#define DSP_BYTES_TO_SAMPLES(bytes) (bytes / (2 * sizeof(uint16_t)))
|
||||||
|
#define DSP_SAMPLES_TO_BYTES(samples) (samples * 2 * sizeof(uint16_t))
|
||||||
|
|
||||||
|
static void ctr_dsp_audio_loop(void* data)
|
||||||
|
{
|
||||||
|
uint32_t pos, buf_pos;
|
||||||
|
ctr_dsp_thread_audio_t *ctr = (ctr_dsp_thread_audio_t*)data;
|
||||||
|
|
||||||
|
if (!ctr)
|
||||||
|
return;
|
||||||
|
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
size_t buf_avail, avail, to_write;
|
||||||
|
slock_lock(ctr->fifo_lock);
|
||||||
|
|
||||||
|
do {
|
||||||
|
avail = FIFO_READ_AVAIL(ctr->fifo);
|
||||||
|
|
||||||
|
if (!avail) {
|
||||||
|
scond_wait(ctr->fifo_avail, ctr->fifo_lock);
|
||||||
|
}
|
||||||
|
} while (!avail && ctr->running);
|
||||||
|
|
||||||
|
slock_unlock(ctr->fifo_lock);
|
||||||
|
|
||||||
|
if (!ctr->running)
|
||||||
|
break;
|
||||||
|
|
||||||
|
pos = ctr->pos;
|
||||||
|
buf_pos = DSP_SAMPLES_TO_BYTES(ndspChnGetSamplePos(ctr->channel));
|
||||||
|
|
||||||
|
buf_avail = buf_pos >= pos ? buf_pos - pos : ctr->fifo_size - pos;
|
||||||
|
to_write = MIN(avail, buf_avail);
|
||||||
|
|
||||||
|
slock_lock(ctr->fifo_lock);
|
||||||
|
|
||||||
|
if (to_write > 0) {
|
||||||
|
fifo_read(ctr->fifo, ctr->dsp_buf.data_pcm8 + pos, to_write);
|
||||||
|
DSP_FlushDataCache(ctr->dsp_buf.data_pcm8 + pos, to_write);
|
||||||
|
scond_signal(ctr->fifo_done);
|
||||||
|
}
|
||||||
|
|
||||||
|
slock_unlock(ctr->fifo_lock);
|
||||||
|
|
||||||
|
if (buf_pos == pos) {
|
||||||
|
svcSleepThread(100000);
|
||||||
|
}
|
||||||
|
|
||||||
|
ctr->pos = (pos + to_write) % ctr->fifo_size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ctr_dsp_thread_audio_free(void *data);
|
||||||
|
|
||||||
|
static void *ctr_dsp_thread_audio_init(const char *device, unsigned rate, unsigned latency,
|
||||||
|
unsigned block_frames,
|
||||||
|
unsigned *new_rate)
|
||||||
|
{
|
||||||
|
ctr_dsp_thread_audio_t *ctr = NULL;
|
||||||
|
|
||||||
|
(void)device;
|
||||||
|
(void)rate;
|
||||||
|
|
||||||
|
if (ndspInit() < 0)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
ctr = (ctr_dsp_thread_audio_t*)calloc(1, sizeof(ctr_dsp_thread_audio_t));
|
||||||
|
|
||||||
|
if (!ctr)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
*new_rate = 32728;
|
||||||
|
|
||||||
|
ctr->running = true;
|
||||||
|
ctr->channel = 0;
|
||||||
|
|
||||||
|
ndspSetOutputMode(NDSP_OUTPUT_STEREO);
|
||||||
|
ndspSetClippingMode(NDSP_CLIP_SOFT); /* ?? */
|
||||||
|
ndspSetOutputCount(2);
|
||||||
|
ndspChnReset(ctr->channel);
|
||||||
|
ndspChnSetFormat(ctr->channel, NDSP_FORMAT_STEREO_PCM16);
|
||||||
|
ndspChnSetInterp(ctr->channel, NDSP_INTERP_NONE);
|
||||||
|
ndspChnSetRate(ctr->channel, 32728.0f);
|
||||||
|
ndspChnWaveBufClear(ctr->channel);
|
||||||
|
|
||||||
|
ctr->fifo_size = DSP_SAMPLES_TO_BYTES((*new_rate * MAX(latency, 8)) / 1000);
|
||||||
|
|
||||||
|
ctr->dsp_buf.data_pcm16 = linearAlloc(ctr->fifo_size);
|
||||||
|
memset(ctr->dsp_buf.data_pcm16, 0, ctr->fifo_size);
|
||||||
|
DSP_FlushDataCache(ctr->dsp_buf.data_pcm16, ctr->fifo_size);
|
||||||
|
|
||||||
|
ctr->dsp_buf.looping = true;
|
||||||
|
ctr->dsp_buf.nsamples = DSP_BYTES_TO_SAMPLES(ctr->fifo_size);
|
||||||
|
ndspChnWaveBufAdd(ctr->channel, &ctr->dsp_buf);
|
||||||
|
|
||||||
|
ctr->fifo = fifo_new(ctr->fifo_size);
|
||||||
|
|
||||||
|
if (!(ctr->fifo_lock = slock_new()) ||
|
||||||
|
!(ctr->fifo_avail = scond_new()) ||
|
||||||
|
!(ctr->fifo_done = scond_new()) ||
|
||||||
|
!(ctr->thread = sthread_create(ctr_dsp_audio_loop, ctr)))
|
||||||
|
{
|
||||||
|
RARCH_LOG("[Audio]: thread creation failed.\n");
|
||||||
|
ctr->running = false;
|
||||||
|
ctr_dsp_thread_audio_free(ctr);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
ctr->pos = 0;
|
||||||
|
ctr->playing = true;
|
||||||
|
|
||||||
|
ctr->frame_time = (retro_time_t)roundf(1000000 * 4481134.0 / (*new_rate * 8192.0));
|
||||||
|
|
||||||
|
ndspSetMasterVol(1.0);
|
||||||
|
|
||||||
|
return ctr;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ctr_dsp_thread_audio_free(void *data)
|
||||||
|
{
|
||||||
|
ctr_dsp_thread_audio_t* ctr = (ctr_dsp_thread_audio_t*)data;
|
||||||
|
if (!ctr)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (ctr->running)
|
||||||
|
{
|
||||||
|
ctr->running = false;
|
||||||
|
scond_signal(ctr->fifo_avail);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ctr->thread)
|
||||||
|
sthread_join(ctr->thread);
|
||||||
|
|
||||||
|
scond_free(ctr->fifo_avail);
|
||||||
|
scond_free(ctr->fifo_done);
|
||||||
|
slock_free(ctr->fifo_lock);
|
||||||
|
|
||||||
|
if (ctr->fifo)
|
||||||
|
{
|
||||||
|
fifo_free(ctr->fifo);
|
||||||
|
ctr->fifo = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
ndspChnWaveBufClear(ctr->channel);
|
||||||
|
|
||||||
|
linearFree(ctr->dsp_buf.data_pcm16);
|
||||||
|
|
||||||
|
free(ctr);
|
||||||
|
ndspExit();
|
||||||
|
ctr = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ssize_t ctr_dsp_thread_audio_write(void *data, const void *buf, size_t size)
|
||||||
|
{
|
||||||
|
size_t avail, written;
|
||||||
|
ctr_dsp_thread_audio_t * ctr = (ctr_dsp_thread_audio_t*)data;
|
||||||
|
|
||||||
|
if (!ctr || !ctr->running)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (ctr->nonblocking)
|
||||||
|
{
|
||||||
|
slock_lock(ctr->fifo_lock);
|
||||||
|
avail = FIFO_WRITE_AVAIL(ctr->fifo);
|
||||||
|
written = MIN(avail, size);
|
||||||
|
if (written > 0)
|
||||||
|
{
|
||||||
|
fifo_write(ctr->fifo, buf, written);
|
||||||
|
scond_signal(ctr->fifo_avail);
|
||||||
|
}
|
||||||
|
slock_unlock(ctr->fifo_lock);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
written = 0;
|
||||||
|
while (written < size && ctr->running)
|
||||||
|
{
|
||||||
|
slock_lock(ctr->fifo_lock);
|
||||||
|
avail = FIFO_WRITE_AVAIL(ctr->fifo);
|
||||||
|
if (avail == 0)
|
||||||
|
{
|
||||||
|
if (ctr->running)
|
||||||
|
{
|
||||||
|
/* Wait a maximum of one frame, skip the write if the thread is still busy */
|
||||||
|
if (!scond_wait_timeout(ctr->fifo_done, ctr->fifo_lock, ctr->frame_time)) {
|
||||||
|
slock_unlock(ctr->fifo_lock);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
slock_unlock(ctr->fifo_lock);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
size_t write_amt = MIN(size - written, avail);
|
||||||
|
fifo_write(ctr->fifo, (const char*)buf + written, write_amt);
|
||||||
|
scond_signal(ctr->fifo_avail);
|
||||||
|
slock_unlock(ctr->fifo_lock);
|
||||||
|
written += write_amt;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return written;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool ctr_dsp_thread_audio_stop(void *data)
|
||||||
|
{
|
||||||
|
ctr_dsp_thread_audio_t* ctr = (ctr_dsp_thread_audio_t*)data;
|
||||||
|
|
||||||
|
if (!ctr)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
ndspSetMasterVol(0.0);
|
||||||
|
ctr->playing = false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool ctr_dsp_thread_audio_alive(void *data)
|
||||||
|
{
|
||||||
|
ctr_dsp_thread_audio_t* ctr = (ctr_dsp_thread_audio_t*)data;
|
||||||
|
|
||||||
|
if (!ctr)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return ctr->playing;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool ctr_dsp_thread_audio_start(void *data, bool is_shutdown)
|
||||||
|
{
|
||||||
|
ctr_dsp_thread_audio_t* ctr = (ctr_dsp_thread_audio_t*)data;
|
||||||
|
|
||||||
|
if (!ctr)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
/* Prevents restarting audio when the menu
|
||||||
|
* is toggled off on shutdown */
|
||||||
|
if (is_shutdown)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
ndspSetMasterVol(1.0);
|
||||||
|
ctr->playing = true;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ctr_dsp_thread_audio_set_nonblock_state(void *data, bool state)
|
||||||
|
{
|
||||||
|
ctr_dsp_thread_audio_t* ctr = (ctr_dsp_thread_audio_t*)data;
|
||||||
|
if (ctr)
|
||||||
|
ctr->nonblocking = state;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool ctr_dsp_thread_audio_use_float(void *data)
|
||||||
|
{
|
||||||
|
(void)data;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static size_t ctr_dsp_thread_audio_write_avail(void *data)
|
||||||
|
{
|
||||||
|
size_t val;
|
||||||
|
ctr_dsp_thread_audio_t* ctr = (ctr_dsp_thread_audio_t*)data;
|
||||||
|
|
||||||
|
slock_lock(ctr->fifo_lock);
|
||||||
|
val = FIFO_WRITE_AVAIL(ctr->fifo);
|
||||||
|
slock_unlock(ctr->fifo_lock);
|
||||||
|
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
|
||||||
|
static size_t ctr_dsp_thread_audio_buffer_size(void *data)
|
||||||
|
{
|
||||||
|
ctr_dsp_thread_audio_t* ctr = (ctr_dsp_thread_audio_t*)data;
|
||||||
|
return ctr->fifo_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
audio_driver_t audio_ctr_dsp_thread = {
|
||||||
|
ctr_dsp_thread_audio_init,
|
||||||
|
ctr_dsp_thread_audio_write,
|
||||||
|
ctr_dsp_thread_audio_stop,
|
||||||
|
ctr_dsp_thread_audio_start,
|
||||||
|
ctr_dsp_thread_audio_alive,
|
||||||
|
ctr_dsp_thread_audio_set_nonblock_state,
|
||||||
|
ctr_dsp_thread_audio_free,
|
||||||
|
ctr_dsp_thread_audio_use_float,
|
||||||
|
"dsp_thread",
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
ctr_dsp_thread_audio_write_avail,
|
||||||
|
ctr_dsp_thread_audio_buffer_size
|
||||||
|
};
|
|
@ -201,8 +201,7 @@ void* linearMemAlign(size_t size, size_t alignment)
|
||||||
void* linearAlloc(size_t size)
|
void* linearAlloc(size_t size)
|
||||||
{
|
{
|
||||||
#if 0
|
#if 0
|
||||||
extern PrintConsole* currentConsole;
|
if(ctrConsole && ctrConsole->consoleInitialised)
|
||||||
if(currentConsole->consoleInitialised)
|
|
||||||
{
|
{
|
||||||
printf("linearAlloc : 0x%08X\n", size);
|
printf("linearAlloc : 0x%08X\n", size);
|
||||||
DEBUG_HOLD();
|
DEBUG_HOLD();
|
||||||
|
|
|
@ -44,7 +44,9 @@ typedef struct
|
||||||
bool isNew3DS;
|
bool isNew3DS;
|
||||||
u32 kernel_fcram_mapping_offset;
|
u32 kernel_fcram_mapping_offset;
|
||||||
|
|
||||||
|
#ifndef USE_CTRULIB_2
|
||||||
Handle arbiter;
|
Handle arbiter;
|
||||||
|
#endif
|
||||||
volatile u32 alloc_address;
|
volatile u32 alloc_address;
|
||||||
volatile u32 alloc_size;
|
volatile u32 alloc_size;
|
||||||
u8* flush_buffer;
|
u8* flush_buffer;
|
||||||
|
@ -263,7 +265,9 @@ static void do_memchunkhax2(void)
|
||||||
|
|
||||||
svcCloseHandle(mch2.dummy_threads_lock);
|
svcCloseHandle(mch2.dummy_threads_lock);
|
||||||
|
|
||||||
|
#ifndef USE_CTRULIB_2
|
||||||
mch2.arbiter = __sync_get_arbiter();
|
mch2.arbiter = __sync_get_arbiter();
|
||||||
|
#endif
|
||||||
|
|
||||||
svcControlMemory(&linear_buffer, 0, 0, 0x1000,
|
svcControlMemory(&linear_buffer, 0, 0, 0x1000,
|
||||||
MEMOP_ALLOC_LINEAR, MEMPERM_READ | MEMPERM_WRITE);
|
MEMOP_ALLOC_LINEAR, MEMPERM_READ | MEMPERM_WRITE);
|
||||||
|
@ -327,9 +331,14 @@ static void do_memchunkhax2(void)
|
||||||
(ThreadFunc)alloc_thread_entry, (u32)&mch2,
|
(ThreadFunc)alloc_thread_entry, (u32)&mch2,
|
||||||
mch2.threads[MCH2_THREAD_COUNT_MAX - 1].stack_top, 0x3F, 1);
|
mch2.threads[MCH2_THREAD_COUNT_MAX - 1].stack_top, 0x3F, 1);
|
||||||
|
|
||||||
|
#ifdef USE_CTRULIB_2
|
||||||
|
while ((u32) syncArbitrateAddress((s32 *)mch2.alloc_address,
|
||||||
|
ARBITRATION_WAIT_IF_LESS_THAN_TIMEOUT, 0) == 0xD9001814);
|
||||||
|
#else
|
||||||
while ((u32) svcArbitrateAddress(mch2.arbiter, mch2.alloc_address,
|
while ((u32) svcArbitrateAddress(mch2.arbiter, mch2.alloc_address,
|
||||||
ARBITRATION_WAIT_IF_LESS_THAN_TIMEOUT, 0,
|
ARBITRATION_WAIT_IF_LESS_THAN_TIMEOUT, 0,
|
||||||
0) == 0xD9001814);
|
0) == 0xD9001814);
|
||||||
|
#endif
|
||||||
|
|
||||||
GX_TextureCopy((void*)linear_buffer, 0, (void*)dst_memchunk, 0, 16, 8);
|
GX_TextureCopy((void*)linear_buffer, 0, (void*)dst_memchunk, 0, 16, 8);
|
||||||
memcpy(flush_buffer, flush_buffer + 0x4000, 0x4000);
|
memcpy(flush_buffer, flush_buffer + 0x4000, 0x4000);
|
||||||
|
|
|
@ -21,6 +21,8 @@ u32 __heapBase;
|
||||||
u32 __stack_bottom;
|
u32 __stack_bottom;
|
||||||
u32 __stack_size_extra;
|
u32 __stack_size_extra;
|
||||||
|
|
||||||
|
u32 __saved_stack;
|
||||||
|
|
||||||
extern u32 __linear_heap_size_hbl;
|
extern u32 __linear_heap_size_hbl;
|
||||||
extern u32 __heap_size_hbl;
|
extern u32 __heap_size_hbl;
|
||||||
extern void* __service_ptr;
|
extern void* __service_ptr;
|
||||||
|
@ -74,6 +76,11 @@ void __system_allocateHeaps(void)
|
||||||
/* Allocate the linear heap */
|
/* Allocate the linear heap */
|
||||||
svcControlMemory(&__linear_heap, 0x0, 0x0, __linear_heap_size, MEMOP_ALLOC_LINEAR, MEMPERM_READ | MEMPERM_WRITE);
|
svcControlMemory(&__linear_heap, 0x0, 0x0, __linear_heap_size, MEMOP_ALLOC_LINEAR, MEMPERM_READ | MEMPERM_WRITE);
|
||||||
|
|
||||||
|
#ifdef USE_CTRULIB_2
|
||||||
|
/* Mappable allocator init */
|
||||||
|
mappableInit(OS_MAP_AREA_BEGIN, OS_MAP_AREA_END);
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Set up newlib heap */
|
/* Set up newlib heap */
|
||||||
fake_heap_end = (char*)0x13F00000;
|
fake_heap_end = (char*)0x13F00000;
|
||||||
}
|
}
|
||||||
|
@ -240,6 +247,9 @@ void __system_initArgv(void)
|
||||||
|
|
||||||
void initSystem(void (*retAddr)(void))
|
void initSystem(void (*retAddr)(void))
|
||||||
{
|
{
|
||||||
|
register u32 sp_val __asm__("sp");
|
||||||
|
__saved_stack = sp_val;
|
||||||
|
|
||||||
__libctru_init(retAddr);
|
__libctru_init(retAddr);
|
||||||
__appInit();
|
__appInit();
|
||||||
__system_initArgv();
|
__system_initArgv();
|
||||||
|
@ -250,6 +260,7 @@ void __attribute__((noreturn)) __ctru_exit(int rc)
|
||||||
{
|
{
|
||||||
__libc_fini_array();
|
__libc_fini_array();
|
||||||
__appExit();
|
__appExit();
|
||||||
|
asm ("mov sp, %[saved_stack] \n\t" : : [saved_stack] "r" (__saved_stack) : "sp");
|
||||||
__libctru_exit(rc);
|
__libctru_exit(rc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,6 @@
|
||||||
|
|
||||||
#include "mini-hb-menu/common.h"
|
#include "mini-hb-menu/common.h"
|
||||||
|
|
||||||
extern const loaderFuncs_s loader_Ninjhax1;
|
|
||||||
extern const loaderFuncs_s loader_Ninjhax2;
|
extern const loaderFuncs_s loader_Ninjhax2;
|
||||||
extern const loaderFuncs_s loader_Rosalina;
|
extern const loaderFuncs_s loader_Rosalina;
|
||||||
|
|
||||||
|
@ -69,12 +68,6 @@ static int exec_3dsx_actual(const char* path,
|
||||||
launch_3dsx = loader_Ninjhax2.launchFile;
|
launch_3dsx = loader_Ninjhax2.launchFile;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!inited)
|
|
||||||
{
|
|
||||||
inited = loader_Ninjhax1.init();
|
|
||||||
launch_3dsx = loader_Ninjhax1.launchFile;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (inited)
|
if (inited)
|
||||||
{
|
{
|
||||||
osSetSpeedupEnable(false);
|
osSetSpeedupEnable(false);
|
||||||
|
|
|
@ -1,43 +0,0 @@
|
||||||
#include "../common.h"
|
|
||||||
|
|
||||||
static void (*callBootloader_1x)(Handle hb, Handle file);
|
|
||||||
static void (*setArgs_1x)(u32* src, u32 length);
|
|
||||||
static Handle fileHandle;
|
|
||||||
|
|
||||||
static bool init(void)
|
|
||||||
{
|
|
||||||
Result res = hbInit();
|
|
||||||
if (R_FAILED(res))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
HB_GetBootloaderAddresses((void**)&callBootloader_1x, (void**)&setArgs_1x);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void deinit(void)
|
|
||||||
{
|
|
||||||
hbExit();
|
|
||||||
}
|
|
||||||
|
|
||||||
static void bootloaderJump(void)
|
|
||||||
{
|
|
||||||
callBootloader_1x(0x00000000, fileHandle);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void launchFile(const char* path, argData_s* args, executableMetadata_s* em)
|
|
||||||
{
|
|
||||||
fileHandle = launchOpenFile(path);
|
|
||||||
if (fileHandle==0)
|
|
||||||
return;
|
|
||||||
setArgs_1x(args->buf, sizeof(args->buf));
|
|
||||||
__system_retAddr = bootloaderJump;
|
|
||||||
}
|
|
||||||
|
|
||||||
const loaderFuncs_s loader_Ninjhax1 =
|
|
||||||
{
|
|
||||||
.name = "ninjhax 1.x",
|
|
||||||
.flags = LOADER_SHOW_REBOOT,
|
|
||||||
.init = init,
|
|
||||||
.deinit = deinit,
|
|
||||||
.launchFile = launchFile,
|
|
||||||
};
|
|
|
@ -60,6 +60,8 @@
|
||||||
static enum frontend_fork ctr_fork_mode = FRONTEND_FORK_NONE;
|
static enum frontend_fork ctr_fork_mode = FRONTEND_FORK_NONE;
|
||||||
static const char* elf_path_cst = "sdmc:/retroarch/retroarch.3dsx";
|
static const char* elf_path_cst = "sdmc:/retroarch/retroarch.3dsx";
|
||||||
|
|
||||||
|
extern bool ctr_bottom_screen_enabled;
|
||||||
|
|
||||||
#ifdef IS_SALAMANDER
|
#ifdef IS_SALAMANDER
|
||||||
static void get_first_valid_core(char* path_return, size_t len)
|
static void get_first_valid_core(char* path_return, size_t len)
|
||||||
{
|
{
|
||||||
|
@ -135,8 +137,6 @@ static void frontend_ctr_deinit(void* data)
|
||||||
u8 not_2DS;
|
u8 not_2DS;
|
||||||
u8 device_model = 0xFF;
|
u8 device_model = 0xFF;
|
||||||
|
|
||||||
extern PrintConsole* currentConsole;
|
|
||||||
|
|
||||||
(void)data;
|
(void)data;
|
||||||
|
|
||||||
#ifndef IS_SALAMANDER
|
#ifndef IS_SALAMANDER
|
||||||
|
@ -153,8 +153,7 @@ static void frontend_ctr_deinit(void* data)
|
||||||
verbosity_enable();
|
verbosity_enable();
|
||||||
retro_main_log_file_init(NULL, false);
|
retro_main_log_file_init(NULL, false);
|
||||||
|
|
||||||
if ((gfxBottomFramebuffers[0] == (u8*)currentConsole->frameBuffer)
|
if (ctr_bottom_screen_enabled && (ctr_fork_mode == FRONTEND_FORK_NONE))
|
||||||
&& (ctr_fork_mode == FRONTEND_FORK_NONE))
|
|
||||||
wait_for_input();
|
wait_for_input();
|
||||||
|
|
||||||
CFGU_GetModelNintendo2DS(¬_2DS);
|
CFGU_GetModelNintendo2DS(¬_2DS);
|
||||||
|
@ -394,6 +393,36 @@ __attribute__((weak)) u32 __ctr_patch_services;
|
||||||
|
|
||||||
void gfxSetFramebufferInfo(gfxScreen_t screen, u8 id);
|
void gfxSetFramebufferInfo(gfxScreen_t screen, u8 id);
|
||||||
|
|
||||||
|
#ifdef USE_CTRULIB_2
|
||||||
|
u8* gfxTopLeftFramebuffers[2];
|
||||||
|
u8* gfxTopRightFramebuffers[2];
|
||||||
|
u8* gfxBottomFramebuffers[2];
|
||||||
|
|
||||||
|
void gfxSetFramebufferInfo(gfxScreen_t screen, u8 id)
|
||||||
|
{
|
||||||
|
if(screen==GFX_TOP)
|
||||||
|
{
|
||||||
|
u8 enable3d = 0;
|
||||||
|
u8 bit5=(enable3d != 0);
|
||||||
|
gspPresentBuffer(GFX_TOP,
|
||||||
|
id,
|
||||||
|
(u32*)gfxTopLeftFramebuffers[id],
|
||||||
|
enable3d ? (u32*)gfxTopRightFramebuffers[id] : (u32*)gfxTopLeftFramebuffers[id],
|
||||||
|
240 * 3,
|
||||||
|
((1)<<8)|((1^bit5)<<6)|((bit5)<<5)|GSP_BGR8_OES);
|
||||||
|
} else {
|
||||||
|
gspPresentBuffer(GFX_BOTTOM,
|
||||||
|
id,
|
||||||
|
(u32*)gfxBottomFramebuffers[id],
|
||||||
|
(u32*)gfxBottomFramebuffers[id],
|
||||||
|
240 * 2,
|
||||||
|
GSP_RGB565_OES);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
PrintConsole* ctrConsole;
|
||||||
|
|
||||||
static void frontend_ctr_init(void* data)
|
static void frontend_ctr_init(void* data)
|
||||||
{
|
{
|
||||||
#ifndef IS_SALAMANDER
|
#ifndef IS_SALAMANDER
|
||||||
|
@ -407,12 +436,25 @@ static void frontend_ctr_init(void* data)
|
||||||
|
|
||||||
u32 topSize = 400 * 240 * 3;
|
u32 topSize = 400 * 240 * 3;
|
||||||
u32 bottomSize = 320 * 240 * 2;
|
u32 bottomSize = 320 * 240 * 2;
|
||||||
|
|
||||||
|
#ifdef USE_CTRULIB_2
|
||||||
|
linearFree(gfxGetFramebuffer(GFX_TOP, GFX_LEFT, NULL, NULL));
|
||||||
|
linearFree(gfxGetFramebuffer(GFX_TOP, GFX_RIGHT, NULL, NULL));
|
||||||
|
linearFree(gfxGetFramebuffer(GFX_BOTTOM, GFX_LEFT, NULL, NULL));
|
||||||
|
gfxSwapBuffers();
|
||||||
|
|
||||||
|
linearFree(gfxGetFramebuffer(GFX_TOP, GFX_LEFT, NULL, NULL));
|
||||||
|
linearFree(gfxGetFramebuffer(GFX_TOP, GFX_RIGHT, NULL, NULL));
|
||||||
|
linearFree(gfxGetFramebuffer(GFX_BOTTOM, GFX_LEFT, NULL, NULL));
|
||||||
|
gfxSwapBuffers();
|
||||||
|
#else
|
||||||
linearFree(gfxTopLeftFramebuffers [0]);
|
linearFree(gfxTopLeftFramebuffers [0]);
|
||||||
linearFree(gfxTopLeftFramebuffers [1]);
|
linearFree(gfxTopLeftFramebuffers [1]);
|
||||||
linearFree(gfxBottomFramebuffers [0]);
|
linearFree(gfxBottomFramebuffers [0]);
|
||||||
linearFree(gfxBottomFramebuffers [1]);
|
linearFree(gfxBottomFramebuffers [1]);
|
||||||
linearFree(gfxTopRightFramebuffers[0]);
|
linearFree(gfxTopRightFramebuffers[0]);
|
||||||
linearFree(gfxTopRightFramebuffers[1]);
|
linearFree(gfxTopRightFramebuffers[1]);
|
||||||
|
#endif
|
||||||
|
|
||||||
gfxTopLeftFramebuffers [0] = linearAlloc(topSize * 2);
|
gfxTopLeftFramebuffers [0] = linearAlloc(topSize * 2);
|
||||||
gfxTopRightFramebuffers[0] = gfxTopLeftFramebuffers[0] + topSize;
|
gfxTopRightFramebuffers[0] = gfxTopLeftFramebuffers[0] + topSize;
|
||||||
|
@ -427,7 +469,7 @@ static void frontend_ctr_init(void* data)
|
||||||
gfxSetFramebufferInfo(GFX_BOTTOM, 0);
|
gfxSetFramebufferInfo(GFX_BOTTOM, 0);
|
||||||
|
|
||||||
gfxSet3D(true);
|
gfxSet3D(true);
|
||||||
consoleInit(GFX_BOTTOM, NULL);
|
ctrConsole = consoleInit(GFX_BOTTOM, NULL);
|
||||||
|
|
||||||
/* enable access to all service calls when possible. */
|
/* enable access to all service calls when possible. */
|
||||||
if (svchax_init)
|
if (svchax_init)
|
||||||
|
@ -440,8 +482,10 @@ static void frontend_ctr_init(void* data)
|
||||||
if (csndInit() != 0)
|
if (csndInit() != 0)
|
||||||
audio_ctr_csnd = audio_null;
|
audio_ctr_csnd = audio_null;
|
||||||
ctr_check_dspfirm();
|
ctr_check_dspfirm();
|
||||||
if (ndspInit() != 0)
|
if (ndspInit() != 0) {
|
||||||
audio_ctr_dsp = audio_null;
|
audio_ctr_dsp = audio_null;
|
||||||
|
audio_ctr_dsp_thread = audio_null;
|
||||||
|
}
|
||||||
cfguInit();
|
cfguInit();
|
||||||
ptmuInit();
|
ptmuInit();
|
||||||
mcuHwcInit();
|
mcuHwcInit();
|
||||||
|
@ -518,7 +562,11 @@ static enum frontend_powerstate frontend_ctr_get_powerstate(
|
||||||
u8 battery_percent = 0;
|
u8 battery_percent = 0;
|
||||||
u8 charging = 0;
|
u8 charging = 0;
|
||||||
|
|
||||||
|
#ifdef USE_CTRULIB_2
|
||||||
|
MCUHWC_GetBatteryLevel(&battery_percent);
|
||||||
|
#else
|
||||||
mcuHwcGetBatteryLevel(&battery_percent);
|
mcuHwcGetBatteryLevel(&battery_percent);
|
||||||
|
#endif
|
||||||
|
|
||||||
*percent = battery_percent;
|
*percent = battery_percent;
|
||||||
/* 3DS does not support seconds of charge remaining */
|
/* 3DS does not support seconds of charge remaining */
|
||||||
|
|
|
@ -24,6 +24,14 @@
|
||||||
#define CTR_TOP_FRAMEBUFFER_WIDTH 400
|
#define CTR_TOP_FRAMEBUFFER_WIDTH 400
|
||||||
#define CTR_TOP_FRAMEBUFFER_HEIGHT 240
|
#define CTR_TOP_FRAMEBUFFER_HEIGHT 240
|
||||||
|
|
||||||
|
#ifdef USE_CTRULIB_2
|
||||||
|
extern u8* gfxTopLeftFramebuffers[2];
|
||||||
|
extern u8* gfxTopRightFramebuffers[2];
|
||||||
|
extern u8* gfxBottomFramebuffers[2];
|
||||||
|
#endif
|
||||||
|
|
||||||
|
extern PrintConsole* ctrConsole;
|
||||||
|
|
||||||
extern const u8 ctr_sprite_shbin[];
|
extern const u8 ctr_sprite_shbin[];
|
||||||
extern const u32 ctr_sprite_shbin_size;
|
extern const u32 ctr_sprite_shbin_size;
|
||||||
|
|
||||||
|
|
|
@ -51,7 +51,7 @@
|
||||||
* Have to keep track of bottom screen enable state
|
* Have to keep track of bottom screen enable state
|
||||||
* externally, otherwise cannot detect current state
|
* externally, otherwise cannot detect current state
|
||||||
* when reinitialising... */
|
* when reinitialising... */
|
||||||
static bool ctr_bottom_screen_enabled = true;
|
bool ctr_bottom_screen_enabled = true;
|
||||||
|
|
||||||
static INLINE void ctr_check_3D_slider(ctr_video_t* ctr, ctr_video_mode_enum video_mode)
|
static INLINE void ctr_check_3D_slider(ctr_video_t* ctr, ctr_video_mode_enum video_mode)
|
||||||
{
|
{
|
||||||
|
@ -325,13 +325,12 @@ static void ctr_set_bottom_screen_enable(void* data, bool enabled)
|
||||||
{
|
{
|
||||||
Handle lcd_handle;
|
Handle lcd_handle;
|
||||||
u8 not_2DS;
|
u8 not_2DS;
|
||||||
extern PrintConsole* currentConsole;
|
|
||||||
ctr_video_t *ctr = (ctr_video_t*)data;
|
ctr_video_t *ctr = (ctr_video_t*)data;
|
||||||
|
|
||||||
if (!ctr)
|
if (!ctr)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
gfxBottomFramebuffers[0] = enabled ? (u8*)currentConsole->frameBuffer:
|
gfxBottomFramebuffers[0] = enabled ? (u8*)ctrConsole->frameBuffer:
|
||||||
(u8*)ctr->empty_framebuffer;
|
(u8*)ctr->empty_framebuffer;
|
||||||
|
|
||||||
CFGU_GetModelNintendo2DS(¬_2DS);
|
CFGU_GetModelNintendo2DS(¬_2DS);
|
||||||
|
@ -568,12 +567,6 @@ static bool ctr_frame(void* data, const void* frame,
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!aptMainLoop())
|
|
||||||
{
|
|
||||||
command_event(CMD_EVENT_QUIT, NULL);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
state_tmp = hidKeysDown();
|
state_tmp = hidKeysDown();
|
||||||
hidTouchRead(&state_tmp_touch);
|
hidTouchRead(&state_tmp_touch);
|
||||||
if((state_tmp & KEY_TOUCH) && (state_tmp_touch.py < 120))
|
if((state_tmp & KEY_TOUCH) && (state_tmp_touch.py < 120))
|
||||||
|
@ -916,6 +909,32 @@ static bool ctr_frame(void* data, const void* frame,
|
||||||
|
|
||||||
/* Swap buffers : */
|
/* Swap buffers : */
|
||||||
|
|
||||||
|
#ifdef USE_CTRULIB_2
|
||||||
|
u32 *buf0, *buf1;
|
||||||
|
u32 stride;
|
||||||
|
|
||||||
|
buf0 = (u32*)gfxTopLeftFramebuffers[ctr->current_buffer_top];
|
||||||
|
|
||||||
|
if(ctr->video_mode == CTR_VIDEO_MODE_2D_800X240)
|
||||||
|
{
|
||||||
|
buf1 = (u32*)(gfxTopLeftFramebuffers[ctr->current_buffer_top] + 240 * 3);
|
||||||
|
stride = 240 * 3 * 2;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (ctr->enable_3d)
|
||||||
|
buf1 = (u32*)gfxTopRightFramebuffers[ctr->current_buffer_top];
|
||||||
|
else
|
||||||
|
buf1 = buf0;
|
||||||
|
|
||||||
|
stride = 240 * 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
u8 bit5 = (ctr->enable_3d != 0);
|
||||||
|
|
||||||
|
gspPresentBuffer(GFX_TOP, ctr->current_buffer_top, buf0, buf1,
|
||||||
|
stride, (1<<8)|((1^bit5)<<6)|((bit5)<<5)|GSP_BGR8_OES);
|
||||||
|
#else
|
||||||
topFramebufferInfo.
|
topFramebufferInfo.
|
||||||
active_framebuf = ctr->current_buffer_top;
|
active_framebuf = ctr->current_buffer_top;
|
||||||
topFramebufferInfo.
|
topFramebufferInfo.
|
||||||
|
@ -953,6 +972,7 @@ static bool ctr_frame(void* data, const void* frame,
|
||||||
framebufferInfoHeader[0x0] ^= 1;
|
framebufferInfoHeader[0x0] ^= 1;
|
||||||
framebufferInfo[framebufferInfoHeader[0x0]] = topFramebufferInfo;
|
framebufferInfo[framebufferInfoHeader[0x0]] = topFramebufferInfo;
|
||||||
framebufferInfoHeader[0x1] = 1;
|
framebufferInfoHeader[0x1] = 1;
|
||||||
|
#endif
|
||||||
|
|
||||||
ctr->current_buffer_top ^= 1;
|
ctr->current_buffer_top ^= 1;
|
||||||
ctr->p3d_event_pending = true;
|
ctr->p3d_event_pending = true;
|
||||||
|
|
|
@ -58,6 +58,20 @@ extern u32 gpuCmdBufOffset;
|
||||||
extern u32 __linear_heap_size;
|
extern u32 __linear_heap_size;
|
||||||
extern u32 __linear_heap;
|
extern u32 __linear_heap;
|
||||||
|
|
||||||
|
#ifdef USE_CTRULIB_2
|
||||||
|
__attribute__((always_inline))
|
||||||
|
static INLINE Result ctrGspSubmitGxCommand(u32 gxCommand[0x8])
|
||||||
|
{
|
||||||
|
return gspSubmitGxCommand(gxCommand);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
__attribute__((always_inline))
|
||||||
|
static INLINE Result ctrGspSubmitGxCommand(u32 gxCommand[0x8])
|
||||||
|
{
|
||||||
|
return gspSubmitGxCommand(gxCmdBuf, gxCommand);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
__attribute__((always_inline))
|
__attribute__((always_inline))
|
||||||
static INLINE Result ctr_set_parallax_layer(bool state)
|
static INLINE Result ctr_set_parallax_layer(bool state)
|
||||||
{
|
{
|
||||||
|
@ -107,7 +121,7 @@ static INLINE Result ctrGuSetCommandList_First(bool queued, u32* buf0a, u32 buf0
|
||||||
gxCommand[6]=(u32)buf2s; //buf2 size
|
gxCommand[6]=(u32)buf2s; //buf2 size
|
||||||
gxCommand[7]=0x0;
|
gxCommand[7]=0x0;
|
||||||
|
|
||||||
return gspSubmitGxCommand(gxCmdBuf, gxCommand);
|
return ctrGspSubmitGxCommand(gxCommand);
|
||||||
}
|
}
|
||||||
|
|
||||||
__attribute__((always_inline))
|
__attribute__((always_inline))
|
||||||
|
@ -121,7 +135,7 @@ static INLINE Result ctrGuSetCommandList_Last(bool queued, u32* buf0a, u32 buf0s
|
||||||
gxCommand[4]=gxCommand[5]=gxCommand[6]=0x0;
|
gxCommand[4]=gxCommand[5]=gxCommand[6]=0x0;
|
||||||
gxCommand[7]=(flags>>1)&1; //when non-zero, call svcFlushProcessDataCache() with the specified buffer
|
gxCommand[7]=(flags>>1)&1; //when non-zero, call svcFlushProcessDataCache() with the specified buffer
|
||||||
|
|
||||||
return gspSubmitGxCommand(gxCmdBuf, gxCommand);
|
return ctrGspSubmitGxCommand(gxCommand);
|
||||||
}
|
}
|
||||||
|
|
||||||
__attribute__((always_inline))
|
__attribute__((always_inline))
|
||||||
|
@ -145,7 +159,7 @@ static INLINE Result ctrGuSetMemoryFill(bool queued, u32* buf0a, u32 buf0v, u32*
|
||||||
gxCommand[6]=(u32)buf1e; //buf1 end addr
|
gxCommand[6]=(u32)buf1e; //buf1 end addr
|
||||||
gxCommand[7]=(width0)|(width1<<16);
|
gxCommand[7]=(width0)|(width1<<16);
|
||||||
|
|
||||||
return gspSubmitGxCommand(gxCmdBuf, gxCommand);
|
return ctrGspSubmitGxCommand(gxCommand);
|
||||||
}
|
}
|
||||||
|
|
||||||
__attribute__((always_inline))
|
__attribute__((always_inline))
|
||||||
|
@ -167,7 +181,7 @@ static INLINE Result ctrGuCopyImage
|
||||||
| ((dst_w > src_w) ? CTRGU_DMA_TRUNCATE : 0);
|
| ((dst_w > src_w) ? CTRGU_DMA_TRUNCATE : 0);
|
||||||
gxCommand[6]=gxCommand[7]=0x0;
|
gxCommand[6]=gxCommand[7]=0x0;
|
||||||
|
|
||||||
return gspSubmitGxCommand(gxCmdBuf, gxCommand);
|
return ctrGspSubmitGxCommand(gxCommand);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -186,7 +200,7 @@ static INLINE Result ctrGuDisplayTransfer
|
||||||
gxCommand[5]=(src_fmt << 8) | (dst_fmt << 12) | multisample_lvl;
|
gxCommand[5]=(src_fmt << 8) | (dst_fmt << 12) | multisample_lvl;
|
||||||
gxCommand[6]=gxCommand[7]=0x0;
|
gxCommand[6]=gxCommand[7]=0x0;
|
||||||
|
|
||||||
return gspSubmitGxCommand(gxCmdBuf, gxCommand);
|
return ctrGspSubmitGxCommand(gxCommand);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -829,7 +829,11 @@ static bool video_thread_init(thread_video_t *thr,
|
||||||
max_size = info.input_scale * RARCH_SCALE_BASE;
|
max_size = info.input_scale * RARCH_SCALE_BASE;
|
||||||
max_size *= max_size;
|
max_size *= max_size;
|
||||||
max_size *= info.rgb32 ? sizeof(uint32_t) : sizeof(uint16_t);
|
max_size *= info.rgb32 ? sizeof(uint32_t) : sizeof(uint16_t);
|
||||||
|
#ifdef _3DS
|
||||||
|
thr->frame.buffer = linearMemAlign(max_size, 0x80);
|
||||||
|
#else
|
||||||
thr->frame.buffer = (uint8_t*)malloc(max_size);
|
thr->frame.buffer = (uint8_t*)malloc(max_size);
|
||||||
|
#endif
|
||||||
|
|
||||||
if (!thr->frame.buffer)
|
if (!thr->frame.buffer)
|
||||||
return false;
|
return false;
|
||||||
|
@ -949,7 +953,11 @@ static void video_thread_free(void *data)
|
||||||
#if defined(HAVE_MENU)
|
#if defined(HAVE_MENU)
|
||||||
free(thr->texture.frame);
|
free(thr->texture.frame);
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef _3DS
|
||||||
|
linearFree(thr->frame.buffer);
|
||||||
|
#else
|
||||||
free(thr->frame.buffer);
|
free(thr->frame.buffer);
|
||||||
|
#endif
|
||||||
slock_free(thr->frame.lock);
|
slock_free(thr->frame.lock);
|
||||||
slock_free(thr->lock);
|
slock_free(thr->lock);
|
||||||
scond_free(thr->cond_cmd);
|
scond_free(thr->cond_cmd);
|
||||||
|
|
|
@ -897,6 +897,7 @@ AUDIO
|
||||||
#elif defined(_3DS)
|
#elif defined(_3DS)
|
||||||
#include "../audio/drivers/ctr_csnd_audio.c"
|
#include "../audio/drivers/ctr_csnd_audio.c"
|
||||||
#include "../audio/drivers/ctr_dsp_audio.c"
|
#include "../audio/drivers/ctr_dsp_audio.c"
|
||||||
|
#include "../audio/drivers/ctr_dsp_thread_audio.c"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef HAVE_XAUDIO
|
#ifdef HAVE_XAUDIO
|
||||||
|
|
|
@ -234,6 +234,8 @@ retro_time_t cpu_features_get_time_usec(void)
|
||||||
return ticks_to_us(OSGetSystemTime());
|
return ticks_to_us(OSGetSystemTime());
|
||||||
#elif defined(SWITCH) || defined(HAVE_LIBNX)
|
#elif defined(SWITCH) || defined(HAVE_LIBNX)
|
||||||
return (svcGetSystemTick() * 10) / 192;
|
return (svcGetSystemTick() * 10) / 192;
|
||||||
|
#elif defined(_3DS)
|
||||||
|
return osGetTime() * 1000;
|
||||||
#elif defined(_POSIX_MONOTONIC_CLOCK) || defined(__QNX__) || defined(ANDROID) || defined(__MACH__) || defined(DJGPP)
|
#elif defined(_POSIX_MONOTONIC_CLOCK) || defined(__QNX__) || defined(ANDROID) || defined(__MACH__) || defined(DJGPP)
|
||||||
struct timespec tv = {0};
|
struct timespec tv = {0};
|
||||||
if (ra_clock_gettime(CLOCK_MONOTONIC, &tv) < 0)
|
if (ra_clock_gettime(CLOCK_MONOTONIC, &tv) < 0)
|
||||||
|
@ -245,8 +247,6 @@ retro_time_t cpu_features_get_time_usec(void)
|
||||||
return ps2_clock() / PS2_CLOCKS_PER_MSEC * 1000;
|
return ps2_clock() / PS2_CLOCKS_PER_MSEC * 1000;
|
||||||
#elif defined(VITA) || defined(PSP)
|
#elif defined(VITA) || defined(PSP)
|
||||||
return sceKernelGetSystemTimeWide();
|
return sceKernelGetSystemTimeWide();
|
||||||
#elif defined(_3DS)
|
|
||||||
return osGetTime() * 1000;
|
|
||||||
#else
|
#else
|
||||||
#error "Your platform does not have a timer function implemented in cpu_features_get_time_usec(). Cannot continue."
|
#error "Your platform does not have a timer function implemented in cpu_features_get_time_usec(). Cannot continue."
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -30,14 +30,24 @@
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <retro_inline.h>
|
#include <retro_inline.h>
|
||||||
|
|
||||||
#define STACKSIZE (4 * 1024)
|
#define STACKSIZE (32 * 1024)
|
||||||
|
|
||||||
|
#ifndef PTHREAD_SCOPE_PROCESS
|
||||||
|
/* An earlier version of devkitARM does not define the pthread types. Can remove in r54+. */
|
||||||
|
|
||||||
typedef Thread pthread_t;
|
typedef Thread pthread_t;
|
||||||
typedef LightLock pthread_mutex_t;
|
typedef LightLock pthread_mutex_t;
|
||||||
typedef void* pthread_mutexattr_t;
|
typedef void* pthread_mutexattr_t;
|
||||||
typedef int pthread_attr_t;
|
typedef int pthread_attr_t;
|
||||||
typedef LightEvent pthread_cond_t;
|
typedef uint32_t pthread_cond_t;
|
||||||
typedef int pthread_condattr_t;
|
typedef int pthread_condattr_t;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint32_t semaphore;
|
||||||
|
LightLock lock;
|
||||||
|
uint32_t waiting;
|
||||||
|
} cond_t;
|
||||||
|
|
||||||
/* libctru threads return void but pthreads return void pointer */
|
/* libctru threads return void but pthreads return void pointer */
|
||||||
static bool mutex_inited = false;
|
static bool mutex_inited = false;
|
||||||
|
@ -56,11 +66,18 @@ static INLINE int pthread_create(pthread_t *thread,
|
||||||
{
|
{
|
||||||
s32 prio = 0;
|
s32 prio = 0;
|
||||||
Thread new_ctr_thread;
|
Thread new_ctr_thread;
|
||||||
|
int procnum = -2; // use default cpu
|
||||||
|
bool isNew3DS;
|
||||||
|
|
||||||
|
APT_CheckNew3DS(&isNew3DS);
|
||||||
|
|
||||||
|
if (isNew3DS)
|
||||||
|
procnum = 2;
|
||||||
|
|
||||||
if (!mutex_inited)
|
if (!mutex_inited)
|
||||||
{
|
{
|
||||||
LightLock_Init(&safe_double_thread_launch);
|
LightLock_Init(&safe_double_thread_launch);
|
||||||
mutex_inited = true;
|
mutex_inited = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*Must wait if attempting to launch 2 threads at once to prevent corruption of function pointer*/
|
/*Must wait if attempting to launch 2 threads at once to prevent corruption of function pointer*/
|
||||||
|
@ -69,27 +86,27 @@ static INLINE int pthread_create(pthread_t *thread,
|
||||||
svcGetThreadPriority(&prio, CUR_THREAD_HANDLE);
|
svcGetThreadPriority(&prio, CUR_THREAD_HANDLE);
|
||||||
|
|
||||||
start_routine_jump = start_routine;
|
start_routine_jump = start_routine;
|
||||||
new_ctr_thread = threadCreate(ctr_thread_launcher, arg, STACKSIZE, prio - 1, -1/*No affinity, use any CPU*/, false);
|
new_ctr_thread = threadCreate(ctr_thread_launcher, arg, STACKSIZE, prio - 1, procnum, false);
|
||||||
|
|
||||||
if (!new_ctr_thread)
|
if (!new_ctr_thread)
|
||||||
{
|
{
|
||||||
LightLock_Unlock(&safe_double_thread_launch);
|
LightLock_Unlock(&safe_double_thread_launch);
|
||||||
return EAGAIN;
|
return EAGAIN;
|
||||||
}
|
}
|
||||||
|
|
||||||
*thread = new_ctr_thread;
|
*thread = (pthread_t)new_ctr_thread;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static INLINE pthread_t pthread_self(void)
|
static INLINE pthread_t pthread_self(void)
|
||||||
{
|
{
|
||||||
return threadGetCurrent();
|
return (pthread_t)threadGetCurrent();
|
||||||
}
|
}
|
||||||
|
|
||||||
static INLINE int pthread_mutex_init(pthread_mutex_t *mutex,
|
static INLINE int pthread_mutex_init(pthread_mutex_t *mutex,
|
||||||
const pthread_mutexattr_t *attr)
|
const pthread_mutexattr_t *attr)
|
||||||
{
|
{
|
||||||
LightLock_Init(mutex);
|
LightLock_Init((LightLock *)mutex);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -101,12 +118,13 @@ static INLINE int pthread_mutex_destroy(pthread_mutex_t *mutex)
|
||||||
|
|
||||||
static INLINE int pthread_mutex_lock(pthread_mutex_t *mutex)
|
static INLINE int pthread_mutex_lock(pthread_mutex_t *mutex)
|
||||||
{
|
{
|
||||||
return LightLock_TryLock(mutex);
|
LightLock_Lock((LightLock *)mutex);
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static INLINE int pthread_mutex_unlock(pthread_mutex_t *mutex)
|
static INLINE int pthread_mutex_unlock(pthread_mutex_t *mutex)
|
||||||
{
|
{
|
||||||
LightLock_Unlock(mutex);
|
LightLock_Unlock((LightLock *)mutex);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -115,6 +133,8 @@ static INLINE void pthread_exit(void *retval)
|
||||||
/*Yes the pointer to int cast is not ideal*/
|
/*Yes the pointer to int cast is not ideal*/
|
||||||
/*threadExit((int)retval);*/
|
/*threadExit((int)retval);*/
|
||||||
(void)retval;
|
(void)retval;
|
||||||
|
|
||||||
|
threadExit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static INLINE int pthread_detach(pthread_t thread)
|
static INLINE int pthread_detach(pthread_t thread)
|
||||||
|
@ -127,68 +147,131 @@ static INLINE int pthread_detach(pthread_t thread)
|
||||||
static INLINE int pthread_join(pthread_t thread, void **retval)
|
static INLINE int pthread_join(pthread_t thread, void **retval)
|
||||||
{
|
{
|
||||||
/*retval is ignored*/
|
/*retval is ignored*/
|
||||||
return threadJoin(thread, U64_MAX);
|
if(threadJoin((Thread)thread, INT64_MAX))
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
threadFree((Thread)thread);
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static INLINE int pthread_mutex_trylock(pthread_mutex_t *mutex)
|
static INLINE int pthread_mutex_trylock(pthread_mutex_t *mutex)
|
||||||
{
|
{
|
||||||
return LightLock_TryLock(mutex);
|
return LightLock_TryLock((LightLock *)mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
static INLINE int pthread_cond_wait(pthread_cond_t *cond,
|
static INLINE int pthread_cond_wait(pthread_cond_t *cond,
|
||||||
pthread_mutex_t *mutex)
|
pthread_mutex_t *mutex)
|
||||||
{
|
{
|
||||||
LightEvent_Wait(cond);
|
cond_t *cond_data = (cond_t *)*cond;
|
||||||
|
LightLock_Lock(&cond_data->lock);
|
||||||
|
cond_data->waiting++;
|
||||||
|
LightLock_Unlock(mutex);
|
||||||
|
LightLock_Unlock(&cond_data->lock);
|
||||||
|
svcWaitSynchronization(cond_data->semaphore, INT64_MAX);
|
||||||
|
LightLock_Lock(mutex);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static INLINE int pthread_cond_timedwait(pthread_cond_t *cond,
|
static INLINE int pthread_cond_timedwait(pthread_cond_t *cond,
|
||||||
pthread_mutex_t *mutex, const struct timespec *abstime)
|
pthread_mutex_t *mutex, const struct timespec *abstime)
|
||||||
{
|
{
|
||||||
for (;;)
|
struct timespec now = {0};
|
||||||
{
|
/* Missing clock_gettime*/
|
||||||
struct timespec now = {0};
|
struct timeval tm;
|
||||||
/* Missing clock_gettime*/
|
int retval = 0;
|
||||||
struct timeval tm;
|
|
||||||
|
|
||||||
gettimeofday(&tm, NULL);
|
cond_t *cond_data = (cond_t *)*cond;
|
||||||
now.tv_sec = tm.tv_sec;
|
LightLock_Lock(&cond_data->lock);
|
||||||
now.tv_nsec = tm.tv_usec * 1000;
|
cond_data->waiting++;
|
||||||
if (LightEvent_TryWait(cond) != 0 || now.tv_sec > abstime->tv_sec || (now.tv_sec == abstime->tv_sec && now.tv_nsec > abstime->tv_nsec))
|
|
||||||
break;
|
gettimeofday(&tm, NULL);
|
||||||
|
now.tv_sec = tm.tv_sec;
|
||||||
|
now.tv_nsec = tm.tv_usec * 1000;
|
||||||
|
s64 timeout = (abstime->tv_sec - now.tv_sec) * 1000000000 + (abstime->tv_nsec - now.tv_nsec);
|
||||||
|
|
||||||
|
if (timeout >= 0) {
|
||||||
|
LightLock_Unlock(mutex);
|
||||||
|
LightLock_Unlock(&cond_data->lock);
|
||||||
|
if (svcWaitSynchronization(cond_data->semaphore, timeout))
|
||||||
|
retval = ETIMEDOUT;
|
||||||
|
|
||||||
|
LightLock_Lock(mutex);
|
||||||
|
} else {
|
||||||
|
retval = ETIMEDOUT;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
static INLINE int pthread_cond_init(pthread_cond_t *cond,
|
static INLINE int pthread_cond_init(pthread_cond_t *cond,
|
||||||
const pthread_condattr_t *attr)
|
const pthread_condattr_t *attr)
|
||||||
{
|
{
|
||||||
LightEvent_Init(cond, RESET_ONESHOT);
|
cond_t *cond_data = calloc(1, sizeof(cond_t));
|
||||||
|
if (!cond_data)
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
if (svcCreateSemaphore(&cond_data->semaphore, 0, 1))
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
LightLock_Init(&cond_data->lock);
|
||||||
|
cond_data->waiting = 0;
|
||||||
|
*cond = (pthread_cond_t)cond_data;
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
error:
|
||||||
|
svcCloseHandle(cond_data->semaphore);
|
||||||
|
if (cond_data)
|
||||||
|
free(cond_data);
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static INLINE int pthread_cond_signal(pthread_cond_t *cond)
|
static INLINE int pthread_cond_signal(pthread_cond_t *cond)
|
||||||
{
|
{
|
||||||
LightEvent_Signal(cond);
|
int32_t count;
|
||||||
|
cond_t *cond_data = (cond_t *)*cond;
|
||||||
|
LightLock_Lock(&cond_data->lock);
|
||||||
|
if (cond_data->waiting) {
|
||||||
|
cond_data->waiting--;
|
||||||
|
LightLock_Unlock(&cond_data->lock);
|
||||||
|
svcReleaseSemaphore(&count, cond_data->semaphore, 1);
|
||||||
|
} else {
|
||||||
|
LightLock_Unlock(&cond_data->lock);
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static INLINE int pthread_cond_broadcast(pthread_cond_t *cond)
|
static INLINE int pthread_cond_broadcast(pthread_cond_t *cond)
|
||||||
{
|
{
|
||||||
LightEvent_Signal(cond);
|
int32_t count;
|
||||||
|
cond_t *cond_data = (cond_t *)*cond;
|
||||||
|
LightLock_Lock(&cond_data->lock);
|
||||||
|
while (cond_data->waiting) {
|
||||||
|
cond_data->waiting--;
|
||||||
|
LightLock_Unlock(&cond_data->lock);
|
||||||
|
svcReleaseSemaphore(&count, cond_data->semaphore, 1);
|
||||||
|
LightLock_Lock(&cond_data->lock);
|
||||||
|
}
|
||||||
|
LightLock_Unlock(&cond_data->lock);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static INLINE int pthread_cond_destroy(pthread_cond_t *cond)
|
static INLINE int pthread_cond_destroy(pthread_cond_t *cond)
|
||||||
{
|
{
|
||||||
/*nothing to destroy*/
|
if (*cond) {
|
||||||
|
cond_t *cond_data = (cond_t *)*cond;
|
||||||
|
|
||||||
|
svcCloseHandle(cond_data->semaphore);
|
||||||
|
free(cond_data);
|
||||||
|
}
|
||||||
|
*cond = 0;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static INLINE int pthread_equal(pthread_t t1, pthread_t t2)
|
static INLINE int pthread_equal(pthread_t t1, pthread_t t2)
|
||||||
{
|
{
|
||||||
if (threadGetHandle(t1) == threadGetHandle(t2))
|
if (threadGetHandle((Thread)t1) == threadGetHandle((Thread)t2))
|
||||||
return 1;
|
return 1;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -446,7 +446,14 @@ libretro_vfs_implementation_file *retro_vfs_file_open_impl(
|
||||||
*/
|
*/
|
||||||
/* TODO: this is only useful for a few platforms,
|
/* TODO: this is only useful for a few platforms,
|
||||||
* find which and add ifdef */
|
* find which and add ifdef */
|
||||||
#if !defined(PSP)
|
#if defined(_3DS)
|
||||||
|
if (stream->scheme != VFS_SCHEME_CDROM)
|
||||||
|
{
|
||||||
|
stream->buf = (char*)calloc(1, 0x10000);
|
||||||
|
if (stream->fp)
|
||||||
|
setvbuf(stream->fp, stream->buf, _IOFBF, 0x10000);
|
||||||
|
}
|
||||||
|
#elif !defined(PSP)
|
||||||
if (stream->scheme != VFS_SCHEME_CDROM)
|
if (stream->scheme != VFS_SCHEME_CDROM)
|
||||||
{
|
{
|
||||||
stream->buf = (char*)calloc(1, 0x4000);
|
stream->buf = (char*)calloc(1, 0x4000);
|
||||||
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -379,6 +379,7 @@ static const audio_driver_t *audio_drivers[] = {
|
||||||
#ifdef _3DS
|
#ifdef _3DS
|
||||||
&audio_ctr_csnd,
|
&audio_ctr_csnd,
|
||||||
&audio_ctr_dsp,
|
&audio_ctr_dsp,
|
||||||
|
&audio_ctr_dsp_thread,
|
||||||
#endif
|
#endif
|
||||||
#ifdef SWITCH
|
#ifdef SWITCH
|
||||||
&audio_switch,
|
&audio_switch,
|
||||||
|
@ -38776,6 +38777,13 @@ static enum runloop_state runloop_check_state(
|
||||||
return RUNLOOP_STATE_QUIT;
|
return RUNLOOP_STATE_QUIT;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef _3DS
|
||||||
|
/* Should be called once per frame */
|
||||||
|
if (!aptMainLoop())
|
||||||
|
return RUNLOOP_STATE_QUIT;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
BIT256_CLEAR_ALL_PTR(¤t_bits);
|
BIT256_CLEAR_ALL_PTR(¤t_bits);
|
||||||
|
|
||||||
p_rarch->input_driver_block_libretro_input = false;
|
p_rarch->input_driver_block_libretro_input = false;
|
||||||
|
|
|
@ -605,6 +605,7 @@ extern audio_driver_t audio_psp;
|
||||||
extern audio_driver_t audio_ps2;
|
extern audio_driver_t audio_ps2;
|
||||||
extern audio_driver_t audio_ctr_csnd;
|
extern audio_driver_t audio_ctr_csnd;
|
||||||
extern audio_driver_t audio_ctr_dsp;
|
extern audio_driver_t audio_ctr_dsp;
|
||||||
|
extern audio_driver_t audio_ctr_dsp_thread;
|
||||||
extern audio_driver_t audio_switch;
|
extern audio_driver_t audio_switch;
|
||||||
extern audio_driver_t audio_switch_thread;
|
extern audio_driver_t audio_switch_thread;
|
||||||
extern audio_driver_t audio_switch_libnx_audren;
|
extern audio_driver_t audio_switch_libnx_audren;
|
||||||
|
|
|
@ -58,7 +58,7 @@
|
||||||
#include "../managers/cheat_manager.h"
|
#include "../managers/cheat_manager.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef HAVE_LIBNX
|
#if defined(HAVE_LIBNX) || defined(_3DS)
|
||||||
#define SAVE_STATE_CHUNK 4096 * 10
|
#define SAVE_STATE_CHUNK 4096 * 10
|
||||||
#else
|
#else
|
||||||
#define SAVE_STATE_CHUNK 4096
|
#define SAVE_STATE_CHUNK 4096
|
||||||
|
|
Loading…
Reference in New Issue