Compare commits

..
Author SHA1 Message Date
Rob Loach 12a130e8c2 Update CHANGES.md 2026-11-11 18:38:28 -05:00
Rob Loach 3cbe16f2cb MCP: two-address conditions, ranges, edge stops 2026-11-10 03:30:37 -05:00
560 changed files with 4406 additions and 81087 deletions

No files matched your search

+1 -30
View File
@@ -102,7 +102,6 @@ jobs:
./vfs_v5_metadata_test
./vfs_readahead_test
./vfs_close_result_test
./vfs_descriptor_rw_test
}
# Mapping on (what the platform actually ships), mapping off
# with the descriptor path forced (what the consoles have),
@@ -147,26 +146,7 @@ jobs:
# The system upgrade runs in the action: an msys2-runtime update
# kills every MSYS2 process, which a run step's own shell would
# not survive.
- name: Set up MSYS2
id: msys2
continue-on-error: true
uses: msys2/setup-msys2@v2
with:
msystem: ${{ matrix.sys }}
update: true
# setup-msys2 has no retry of its own, and its system upgrade fails
# the job when mirror.msys2.org stalls ("Operation too slow") on the
# package databases. A failed attempt is run once more after a
# minute; the second reinstalls over the first.
- name: Wait before retrying MSYS2
if: steps.msys2.outcome == 'failure'
shell: bash
run: sleep 60
- name: Set up MSYS2 (retry)
if: steps.msys2.outcome == 'failure'
uses: msys2/setup-msys2@v2
- uses: msys2/setup-msys2@v2
with:
msystem: ${{ matrix.sys }}
update: true
@@ -226,15 +206,6 @@ jobs:
./vfs_prefetch_offthread_test.exe
# The descriptor path's close() result, with PS2's semantics.
./vfs_close_result_test.exe
# Read-write descriptor streams on the Windows C runtimes,
# and that a file they create is writable afterwards.
./vfs_descriptor_rw_test.exe
# Reads and appends at offsets from several threads through
# the second handle: opened relative to the stream's, the same
# checked as before Vista, and by the path; a -1 fails each.
./vfs_positional_nommap_test.exe
./vfs_positional_ntverify_test.exe
./vfs_positional_pathreopen_test.exe
# The Win64 fastjmp_set stores xmm6-xmm15 with movaps and faults
# on a misaligned buffer. Linux has no such stores, so the Linux
-19
View File
@@ -7,10 +7,6 @@ name: CI Linux EGL hardware core
# bound to the window surface the video thread holds, and with it off.
# Mesa takes the surfaceless path by itself; a preloaded shim hides
# parts of its EGL so the pbuffer paths run too.
#
# Then a core that draws on a thread of its own through
# RETRO_ENVIRONMENT_GET_HW_SHARED_CONTEXT_INTERFACE, on GLX and on EGL,
# threaded and not: the colour on screen must be that thread's drawing.
on:
push:
@@ -25,10 +21,6 @@ on:
- 'gfx/video_thread_hw.c'
- 'gfx/video_thread_wrapper.c'
- 'samples/gfx/egl_hw_core/**'
- 'samples/gfx/gl_shared_context/**'
- 'gfx/drivers_context/x_ctx.c'
- 'runloop.c'
- 'libretro-common/include/libretro.h'
- '.github/workflows/Linux-egl-hw-core.yml'
pull_request:
paths:
@@ -40,10 +32,6 @@ on:
- 'gfx/video_thread_hw.c'
- 'gfx/video_thread_wrapper.c'
- 'samples/gfx/egl_hw_core/**'
- 'samples/gfx/gl_shared_context/**'
- 'gfx/drivers_context/x_ctx.c'
- 'runloop.c'
- 'libretro-common/include/libretro.h'
- '.github/workflows/Linux-egl-hw-core.yml'
workflow_dispatch:
@@ -137,13 +125,6 @@ jobs:
make -C samples/gfx/egl_hw_core
timeout 600 python3 samples/gfx/egl_hw_core/egl_hw_core_test.py ./retroarch
- name: Run gl_shared_context_test
shell: bash
run: |
set -eu
make -C samples/gfx/gl_shared_context
timeout 300 python3 samples/gfx/gl_shared_context/gl_shared_context_test.py ./retroarch
- name: Save ccache
# Only master's pushes keep a cache: pull requests restore
# master's, so one push does not evict the next one's.
@@ -171,9 +171,6 @@ jobs:
make -C ../tls_retro clean
SSL_BACKEND=$be ../tls_retro/verify_hook_test.sh
make -C ../tls_retro clean
SSL_BACKEND=$be CFLAGS='-O1 -g1 -std=gnu89 -Wall -Wextra -Werror=declaration-after-statement -fsanitize=address,undefined -fno-omit-frame-pointer' \
sh ../tls_retro/handshake_test.sh
make -C ../tls_retro clean
- name: Operate the libsmb2 backend (SMB VFS against a local smbd)
if: matrix.lane == 'libsmb2'
@@ -125,12 +125,7 @@ jobs:
rtmp_publish_test
rtmp_control_test
rtmp_session_test
rtmp_client_test
rtmp_socket_test
rtmp_connect_test
rtmp_connect_select_test
rtmp_resolve_test
rtmp_resolve_native_test
rslc_test
rslc_build_test
rslc_ext_test
@@ -139,8 +134,6 @@ jobs:
s16_to_float_test
float_to_s16_test
float_to_s32_test
# G.711 mu-law; a step below compares it with FFmpeg's.
float_to_ulaw_test
compat_fnmatch_test
snprintf
unbase64_test
@@ -153,11 +146,8 @@ jobs:
rzstd_raw_block_test_novec
rzstd_dict_test
rbzip2_test
shiftjis_test
rinflate_window_test
rdeflate_hash_test
rdeflate_flush_test
encoding_adler32_test
emscripten_mmap_test
archive_zip_test
archive_zstd_test
@@ -173,19 +163,7 @@ jobs:
fill_pathname_test
path_mkdir_test
path_parent_dir_test
# path_remove_tree and path_copy_tree on a real tree, links
path_tree_test
rpng
# a PNG a row at a time, as stored, from input in pieces
rpng_rows_test
# a GIF's first image, straight into the caller's rows
rgif_test
# YAML: configurations, block scalars, a patch file whose
# entries name anchored sequences by alias, node locations
ryaml_test
# what the YAML writer writes reads back the same, over
# tricky scalars and 3000 random documents
ryaml_writer_test
rzip_chunk_size_test
rzip_matches_buf_test
rzip_codec_test
@@ -197,41 +175,6 @@ jobs:
# rvorbis' codebook size bound, and a real stream past it.
rvorbis_codebook_test
rjpeg_test
# Baseline JPEG encoding, decoded back with rjpeg; a step
# below has FFmpeg decode what it writes.
rjpeg_encode_test
# MP4 writing, read back with rmp4; a step below has FFmpeg
# decode the files.
rmp4_mux_test
# MPEG-2 video through rmpeg1_video, on its own fixtures; the
# step below runs it again over FFmpeg's and the conformance
# streams.
rmpeg2_test
# MPEG-4 Part 2 video through rmpeg4_video, on its own
# fixtures, whole, a unit at a time and damaged; a step below
# runs it over FFmpeg's and Xvid's streams.
rmpeg4_test
# MPEG-4 Part 2 encoding, decoded back with rmpeg4_video; a
# step below has FFmpeg decode the streams.
rmpeg4_encode_test
# AAC-LC encoding, decoded back with raac; a step below has
# FFmpeg decode the streams.
raac_encode_test
# H.264 encoding, decoded back with rh264; a step below has
# FFmpeg decode the streams.
rh264_encode_test
# Tags in each container and ID3 version, and every prefix
# and corruption of each file read inside it.
rtags_test
# A file's audio_transfer arm from its bytes, and the folds.
audio_transfer_sniff_test
# ATRAC3 and ATRAC3plus in WAVE and OpenMG through audio_transfer.
audio_transfer_atrac_test
# AVI and ASF headers: streams, codecs, sizes, rates, length.
rcontainer_test
# 4:2:0 to bytes in memory order and to UYVY, and bytes to
# 4:2:0; a step below compares the latter with swscale's.
image_yuv_test
rh264_lossless_test
rh264_lossless_test_nothreads
rh264_lossless_test_volatile
@@ -241,8 +184,6 @@ jobs:
rh264_state_test
# rmp3's frame-at-a-time API against its pull API.
rmp3_frame_test
# rmp3's gapless trimming against ffmpeg's, and its tag parser.
rmp3_gapless_test
# raac_last_size over units followed by more.
raac_size_test
# raac's savestates: saved between units, loaded into a new decoder.
@@ -262,7 +203,6 @@ jobs:
r7z_stored_test
r7z_methods_test
r7z_stream_test
r7z_peek_threads_test
rzip_archive_test
# The RAR reader on real archives (LZ and PPMd blocks,
# filters, Unicode names) and on mangled copies of them.
@@ -285,25 +225,6 @@ jobs:
filestream_rbuf_fault_test
vfs_rename_replace_test
vfs_close_result_test
# A read-write stream on the descriptor path, as an emulated
# file system uses it: in-place writes, truncate, reopen.
vfs_descriptor_rw_test
# Positional I/O (VFS v6): reads at offsets and appends from
# several threads on one stream, with no lock.
vfs_positional_test
# intfstream reads at offsets on file, buffered and memory
# streams: position kept, window kept, four threads.
intfstream_read_at_test
# The same without HAVE_MMAP (Android's build): pread/pwrite
# are still there, so a -1 fails.
vfs_positional_nommap_test
# Where off_t is 32 bits: past 4 GiB refused, never read
# 4 GiB lower.
vfs_positional_off32_test
# Windows NT before Vista's second handle (the path, checked);
# the same run as vfs_positional_test here.
vfs_positional_pathreopen_test
vfs_positional_ntverify_test
cdrom_cuesheet_overflow_test
rdvd_h262_test
rdvd_lpcm_test
@@ -332,15 +253,6 @@ jobs:
http_parse_test
# UPnP gateway client: parsers, and SOAP against a fake gateway.
net_upnp_test
# net_http: a 3xx handed back unfollowed, a DELETE body's
# Content-Length, the caller's Accept-Encoding/User-Agent.
net_http_options_test
# socket_poll past FD_SETSIZE sockets.
socket_poll_test
# Half floats both ways, against F16C.
float16_test
# TrueType and CID-keyed CFF glyphs, metrics and kerning.
rtt_test
rjson_test
rm3u_test
rmp4_fragment_test
@@ -452,16 +364,6 @@ jobs:
# forces every tier on Linux, Windows and macOS runners.
retro_procbarrier_test
retro_asym_eventcount_test
# Two processes hand a counter back and forth 200000 times,
# each parked between turns: a lost wake hangs it, and its
# own watchdog reports that as a failure.
retro_shared_eventcount_test
# A writer updates a record two million times while three
# threads copy it: no copy torn, none going back.
retro_seqlock_test
# Twenty threads change one record two million times in all
# while three copy it: no change lost, no copy torn.
retro_cas_record_test
sthread_ex_test
fast_cores_test
memshm_test
@@ -505,11 +407,6 @@ jobs:
# stereo stream (tones, gain points, swap and negate masks)
# and a mono one, then bad frames and garbage.
ratrac3p_test
# ATRAC9 against a reference decoder's output for generated
# streams in every channel layout, rate and superframe size,
# with reset and savestates; then its own unit checks.
ratrac9_vectors_test
ratrac9_test
# Animation playback against a scripted stream: order,
# pacing, loops, catch-up, the worker's two jobs.
video_player_test
@@ -799,435 +696,6 @@ jobs:
ffmpeg -hide_banner -loglevel error -i "$fixture" -pix_fmt yuv420p -f rawvideo -y "$reference"
./rdvd_h262_test "$fixture" "$reference"
# The ISO/IEC 13818-4 streams never change (their md5s are checked):
# one good download is kept in the Actions cache
- name: Restore the MPEG-2 conformance streams
if: matrix.group == 'formats'
id: mpeg2_conformance
uses: actions/cache/restore@v4
with:
path: ~/mpeg2-conformance
key: mpeg2-conformance-main-8-1
# MPEG-2 video against FFmpeg's decode, within 3 per sample (two
# IEEE 1180 inverse transforms): streams FFmpeg writes, progressive,
# interlaced (field DCT, field motion) and with Table B.15, alternate
# scan, the non-linear quantiser and 10-bit intra DC; and conformance
# streams with field pictures, dual prime, frame and field pictures
# mixed, slices starting mid-row
- name: Decode MPEG-2 video against FFmpeg and conformance streams
if: matrix.group == 'formats'
shell: bash
working-directory: libretro-common/samples/formats/mpeg2
run: |
set -euo pipefail
make -j2 SANITIZER=address,undefined
work=$(mktemp -d)
trap 'rm -rf "$work"' EXIT
src="-f lavfi -i testsrc2=size=352x288:rate=25,format=yuv420p -frames:v 24"
i=0
for opts in "-bf 2 -g 12 -q:v 4" "-bf 2 -g 12 -q:v 4 -flags +ildct+ilme -top 1" \
"-bf 2 -g 12 -q:v 3 -qmax 28 -intra_vlc 1 -non_linear_quant 1 -alternate_scan 1 -dc 10"; do
i=$((i+1))
ffmpeg -hide_banner -loglevel error $src -c:v mpeg2video $opts -f mpeg2video -y "$work/g$i.m2v"
ffmpeg -hide_banner -loglevel error -i "$work/g$i.m2v" -fps_mode passthrough \
-pix_fmt yuv420p -f rawvideo -y "$work/g$i.yuv"
./rmpeg2_test "$work/g$i.m2v" "$work/g$i.yuv"
done
conf="$HOME/mpeg2-conformance"
mkdir -p "$conf"
base=https://standards.iso.org/ittf/PubliclyAvailableStandards/ISO_IEC_13818-4_2004_Conformance_Testing/Video/bitstreams/main-profile
# A stream the server will not give is reported and left out
# rather than failing the job; the cache is saved only once every
# stream is in it, and kept from then on
missing=0
while read -r path md5; do
f="$conf/$(basename "$path")"
if ! { [ -f "$f" ] && echo "$md5 $f" | md5sum --quiet -c -; }; then
if ! curl --fail --silent --show-error --location --retry 3 --retry-all-errors \
--retry-max-time 60 --connect-timeout 10 --max-time 60 "$base/$path" -o "$f" \
|| ! echo "$md5 $f" | md5sum --quiet -c -; then
echo "::warning title=MPEG-2 conformance::$path could not be fetched; left out"
rm -f "$f"
missing=1
continue
fi
fi
gunzip -c "$f" > "$work/c.m2v"
ffmpeg -nostdin -hide_banner -loglevel error -i "$work/c.m2v" -fps_mode passthrough \
-pix_fmt yuv420p -f rawvideo -y "$work/c.yuv"
./rmpeg2_test "$work/c.m2v" "$work/c.yuv"
done <<'LIST'
tcela/tcela-8-fp-dp/tcela-8.bits.gz f0ef12c0e4f4a6cdb9ba42d000054c8b
hhi/hhi_burst_short/hhi_burst_short.bits.gz a68d3436d89ffc896393b18e8556a33c
nokia/nokia6/nokia6_dual.bit.gz 9890f21e949716f67469240d4e3105c0
toshiba/toshiba_DPall-0/toshiba_DPall-0.mpg.gz d92090842a0c2e37cf1cda7212868cc3
sony/sony-ct3/sony-ct3.bs.gz 31bb0abfaf802c754254b38b500d7685
tcela/tcela-6-slices/tcela-6.bits.gz 1247cf986205e7dfe4413bd223be8ee6
mei/mei.2conftest.4f/mei_2stream.4f.gz 505375e1f68fe527f52eb3604cc8edae
ti/TI_cl_2/TI_c1_2.bits.gz 3b25d76d4b517ec3ab493f2f3fb767c0
LIST
[ "$missing" = 0 ] && touch "$conf/complete" || rm -f "$conf/complete"
- name: Save the MPEG-2 conformance streams
if: matrix.group == 'formats' && steps.mpeg2_conformance.outputs.cache-hit != 'true' && hashFiles('~/mpeg2-conformance/complete') != ''
uses: actions/cache/save@v4
with:
path: ~/mpeg2-conformance
key: mpeg2-conformance-main-8-1
# MPEG-4 Part 2 video against FFmpeg's decode, within 3 per sample:
# streams FFmpeg's mpeg4 encoder writes (B-VOPs, quarter sample, four
# vectors, MPEG quantisation, interlaced field DCT and motion with
# alternate scan, AC prediction, resync markers, data partitioning, a
# size not a multiple of 16), Xvid's
# (GMC S-VOPs), and H.263 for the short video header, with and
# without GOB headers. FFmpeg decodes with one thread: its frame
# threads do not share the field vectors interlaced direct mode reads.
# What rjpeg_encode writes - 4:2:0 and 4:2:2, sizes in and out of
# whole MCUs, qualities 20 to 100 - must decode in FFmpeg with no
# error
- name: Decode rjpeg_encode's JPEGs with FFmpeg
if: matrix.group == 'formats'
shell: bash
working-directory: libretro-common/samples/formats/jpeg_encode
run: |
set -euo pipefail
make -j2 SANITIZER=address,undefined
work=$(mktemp -d)
trap 'rm -rf "$work"' EXIT
./rjpeg_encode_test "$work"
n=0
for f in "$work"/*.jpg; do
ffmpeg -nostdin -hide_banner -loglevel error -xerror -i "$f" -f null -
n=$((n+1))
done
[ "$n" = 9 ]
# What rmp4_mux writes - MPEG-4 video with B-VOPs and 16-bit PCM,
# motion JPEG and float PCM - must decode in FFmpeg with no error,
# every frame there and the first shown at time zero
- name: Read rmp4_mux's files with FFmpeg
if: matrix.group == 'formats'
shell: bash
working-directory: libretro-common/samples/formats/mp4_mux
run: |
set -euo pipefail
make -j2 SANITIZER=address,undefined
work=$(mktemp -d)
trap 'rm -rf "$work"' EXIT
./rmp4_mux_test "$work"
for f in mpeg4_pcm:8 mjpeg_f32:6; do
file="$work/${f%%:*}.mp4"
ffmpeg -nostdin -hide_banner -loglevel error -xerror -i "$file" -f null -
got=$(ffprobe -v error -count_frames -select_streams v \
-show_entries stream=nb_read_frames,start_time -of csv=p=0 "$file")
echo "$file: $got"
[ "$got" = "0.000000,${f##*:}" ]
done
- name: Decode MPEG-4 video against FFmpeg
if: matrix.group == 'formats'
shell: bash
working-directory: libretro-common/samples/formats/mpeg4
run: |
set -euo pipefail
make -j2 SANITIZER=address,undefined
work=$(mktemp -d)
trap 'rm -rf "$work"' EXIT
i=0
while IFS='|' read -r size fmt opts; do
i=$((i+1))
ffmpeg -nostdin -hide_banner -loglevel error \
-f lavfi -i "testsrc2=size=$size:rate=25,format=yuv420p" -frames:v 24 \
$opts -f "$fmt" -y "$work/s$i.bin"
ffmpeg -nostdin -hide_banner -loglevel error -threads 1 -flags +bitexact -idct simple \
-f "$fmt" -i "$work/s$i.bin" -fps_mode passthrough -pix_fmt yuv420p -f rawvideo -y "$work/s$i.yuv"
./rmpeg4_test "$work/s$i.bin" "$work/s$i.yuv"
done <<'LIST'
352x288|m4v|-c:v mpeg4 -g 12 -bf 2 -q:v 4
352x288|m4v|-c:v mpeg4 -g 12 -bf 2 -q:v 4 -flags +qpel+mv4
352x288|m4v|-c:v mpeg4 -g 12 -bf 2 -q:v 4 -mpeg_quant 1
352x288|m4v|-c:v mpeg4 -g 12 -bf 2 -q:v 4 -flags +ildct+ilme
352x288|m4v|-c:v mpeg4 -g 12 -bf 2 -q:v 3 -mpeg_quant 1 -flags +ildct+ilme+qpel -alternate_scan 1
352x288|m4v|-c:v mpeg4 -g 12 -bf 2 -q:v 8 -flags +aic
352x288|m4v|-c:v mpeg4 -g 12 -bf 2 -q:v 4 -ps 400
352x288|m4v|-c:v mpeg4 -g 12 -bf 0 -q:v 6 -ps 300 -data_partitioning 1 -flags +mv4+aic
350x286|m4v|-c:v mpeg4 -g 12 -bf 2 -q:v 4 -flags +mv4+qpel
352x288|m4v|-c:v libxvid -g 8 -bf 0 -q:v 4 -gmc 1 -flags +qpel+mv4
352x288|m4v|-c:v libxvid -g 8 -bf 0 -q:v 4 -flags +ildct
176x144|h263|-c:v h263 -g 12 -q:v 5
352x288|h263|-c:v h263 -g 12 -q:v 5 -ps 300
LIST
# What rmpeg4_encode writes - whole macroblocks and not, fine and
# coarse quantisers, a bit rate - FFmpeg decodes within 3 per sample
# of rmpeg4_video, which decodes it exactly as the encoder
# reconstructed it (the sample checks that)
- name: Decode rmpeg4_encode's streams with FFmpeg
if: matrix.group == 'formats'
shell: bash
working-directory: libretro-common/samples/formats
run: |
set -euo pipefail
make -C mpeg4 -j2 SANITIZER=address,undefined
make -C mpeg4_encode -j2 SANITIZER=address,undefined
work=$(mktemp -d)
trap 'rm -rf "$work"' EXIT
./mpeg4_encode/rmpeg4_encode_test "$work"
n=0
for f in "$work"/*.m4v; do
ffmpeg -nostdin -hide_banner -loglevel error -xerror -threads 1 -flags +bitexact -idct simple \
-i "$f" -pix_fmt yuv420p -f rawvideo -y "${f%.m4v}.yuv"
./mpeg4/rmpeg4_test "$f" "${f%.m4v}.yuv"
n=$((n+1))
done
[ "$n" = 5 ]
# What raac_encode writes - tones, noise, an attack, mono and
# stereo, 8 to 96 kHz - FFmpeg decodes within 2 per sample of raac
# (the sample checks raac's decoding against the input)
- name: Decode raac_encode's streams with FFmpeg
if: matrix.group == 'formats'
shell: bash
working-directory: libretro-common/samples/formats/aac_encode
run: |
set -euo pipefail
make -j2 SANITIZER=address,undefined
work=$(mktemp -d)
trap 'rm -rf "$work"' EXIT
./raac_encode_test "$work"
n=0
for f in "$work"/*.aac; do
ffmpeg -nostdin -hide_banner -loglevel error -xerror -i "$f" \
-f s16le -y "${f%.aac}.ff.s16"
./raac_encode_test --compare "${f%.aac}.s16" "${f%.aac}.ff.s16"
n=$((n+1))
done
[ "$n" = 9 ]
# What rh264_encode writes - whole macroblocks and cropped, fine
# and coarse quantisers, a bit rate - FFmpeg decodes to exactly the
# encoder's reconstruction, as rh264 does (the sample checks that)
- name: Decode rh264_encode's streams with FFmpeg
if: matrix.group == 'formats'
shell: bash
working-directory: libretro-common/samples/formats/h264_encode
run: |
set -euo pipefail
make -j2 SANITIZER=address,undefined
work=$(mktemp -d)
trap 'rm -rf "$work"' EXIT
./rh264_encode_test "$work"
n=0
for f in "$work"/*.264; do
ffmpeg -nostdin -hide_banner -loglevel error -xerror -i "$f" \
-f rawvideo -pix_fmt yuv420p -y "${f%.264}.ff.yuv"
cmp "${f%.264}.yuv" "${f%.264}.ff.yuv"
n=$((n+1))
done
[ "$n" = 5 ]
# What FFmpeg writes as tags - ID3v2.3 and 2.4, ID3v1 alone, FLAC,
# Vorbis and Opus in Ogg, MP4, ASF, WAVE - rtags reads as ffprobe
# does, non-ASCII text, numbered genres and full dates in
- name: Read FFmpeg's tags with rtags
if: matrix.group == 'formats'
shell: bash
working-directory: libretro-common/samples/formats/tags
run: |
set -euo pipefail
make -j2 SANITIZER=address,undefined
work=$(mktemp -d)
trap 'rm -rf "$work"' EXIT
tags=(-metadata 'title=Tïtle ☃' -metadata 'artist=Ärtist'
-metadata 'album=Albüm' -metadata genre=Rock -metadata track=3/12
-metadata disc=1/2 -metadata date=2004)
enc() { ffmpeg -nostdin -hide_banner -loglevel error -f lavfi -i sine=d=0.2 "$@"; }
enc "${tags[@]}" -id3v2_version 3 -y "$work/v23.mp3"
enc "${tags[@]}" -id3v2_version 4 -y "$work/v24.mp3"
enc -id3v2_version 3 -metadata genre=17 -metadata date=2004-05-01 \
-metadata 'title=a long title with a snowman, ☃' -y "$work/genre.mp3"
enc "${tags[@]}" -write_id3v1 1 -y "$work/both.mp3"
# ID3v1 alone: the ID3v2 tag in front cut off
python3 -c 'import sys
d = open(sys.argv[1], "rb").read()
s = (d[6] & 127) << 21 | (d[7] & 127) << 14 | (d[8] & 127) << 7 | (d[9] & 127)
open(sys.argv[2], "wb").write(d[10 + s:])' "$work/both.mp3" "$work/v1.mp3"
rm "$work/both.mp3"
enc "${tags[@]}" -y "$work/a.flac"
enc "${tags[@]}" -c:a libvorbis -y "$work/a.ogg"
enc "${tags[@]}" -c:a libopus -y "$work/a.opus"
enc "${tags[@]}" -y "$work/a.m4a"
enc -metadata genre=17 -metadata date=2004-05-01 -y "$work/b.m4a"
enc "${tags[@]}" -y "$work/a.wma"
enc "${tags[@]}" -y "$work/a.wav"
n=0
for f in "$work"/*.*; do
ffprobe -v error -show_entries format_tags:stream_tags \
-of default=nw=1 "$f" > "$f.tags"
./rtags_test --ffprobe "$f" "$f.tags"
n=$((n+1))
done
[ "$n" = 11 ]
# Files FFmpeg writes - MP3 with and without ID3v2, ADTS with and
# without, M4A, FLAC, Ogg Vorbis, Opus, WAVE PCM and float, WMA1/2,
# AC-3 - each sniffed as its arm and decoded where the sniffer
# says; and 5.1 with a tone a channel in each multichannel arm,
# folded with audio_transfer_stereo_matrix: every tone on its side
- name: Sniff and fold FFmpeg's files with audio_transfer
if: matrix.group == 'formats'
shell: bash
working-directory: libretro-common/samples/formats/audio_transfer_sniff
run: |
set -euo pipefail
make -j2 SANITIZER=address,undefined
work=$(mktemp -d)
trap 'rm -rf "$work"' EXIT
enc() { ffmpeg -nostdin -hide_banner -loglevel error \
-f lavfi -i sine=f=440:d=1:sample_rate=48000 -ac 2 "$@"; }
enc -metadata title=t -y "$work/id3.mp3"
enc -id3v2_version 0 -write_xing 0 -y "$work/bare.mp3"
enc -c:a aac -f adts -y "$work/bare.aac"
enc -c:a aac -f adts -write_id3v2 1 -metadata title=t -y "$work/id3.aac"
enc -y "$work/a.m4a"
enc -y "$work/a.flac"
enc -c:a libvorbis -y "$work/a.ogg"
enc -c:a libopus -y "$work/a.opus"
enc -y "$work/s16.wav"
enc -c:a pcm_f32le -y "$work/f32.wav"
enc -c:a wmav1 -y "$work/v1.wma"
enc -y "$work/v2.wma"
enc -c:a ac3 -y "$work/a.ac3"
for p in id3.mp3:mp3 bare.mp3:mp3 bare.aac:aac id3.aac:aac a.m4a:aac \
a.flac:flac a.ogg:vorbis a.opus:opus s16.wav:wav f32.wav:wav \
v1.wma:wma v2.wma:wma a.ac3:ac3; do
./audio_transfer_sniff_test --file "$work/${p%%:*}" "${p#*:}"
done
# MP3, gapless (LAME tag) and not: FFmpeg's samples, where they
# start and end
for f in id3.mp3 bare.mp3; do
ffmpeg -nostdin -hide_banner -loglevel error -i "$work/$f" -f f32le -y "$work/$f.f32"
./audio_transfer_sniff_test --file "$work/$f" mp3 --pcm "$work/$f.f32"
done
# WMA: the length the ASF header states, as ffprobe reads it
for f in v1.wma v2.wma; do
frames=$(ffprobe -v error -show_entries format=duration:stream=sample_rate \
-of csv=p=0 "$work/$f" | tr '\n' ' ' | awk '{ printf "%d", $1 * $2 + 0.5 }')
./audio_transfer_sniff_test --file "$work/$f" wma --frames "$frames"
done
# WMA1 and WMA2, gapless at each frame size (2048, 1024 and 512
# samples): the signal FFmpeg's encoder was given, from its
# first sample, at the length the header states
for codec in wmav1 wmav2; do
for rate in 44100 22050 16000 8000; do
src="sine=f=440:d=0.73:sample_rate=$rate"
ffmpeg -nostdin -hide_banner -loglevel error -f lavfi -i "$src" -ac 2 \
-c:a "$codec" -y "$work/g.wma"
ffmpeg -nostdin -hide_banner -loglevel error -f lavfi -i "$src" -ac 2 \
-f f32le -y "$work/g.f32"
./audio_transfer_sniff_test --file "$work/g.wma" wma --source "$work/g.f32"
done
done
six=""
n=0
for hz in 300 500 700 80 1100 1300; do
six="${six}sine=f=$hz:d=2:sample_rate=48000[c$n];"
n=$((n+1))
done
six="${six}[c0][c1][c2][c3][c4][c5]join=inputs=6:channel_layout=5.1"
six="$six:map=0.0-FL|1.0-FR|2.0-FC|3.0-LFE|4.0-BL|5.0-BR"
for p in m4a:aac:aac ogg:libvorbis:vorbis opus:libopus:opus \
flac:flac:flac ac3:ac3:ac3 wav:pcm_s16le:wav; do
IFS=: read -r ext codec type <<< "$p"
ffmpeg -nostdin -hide_banner -loglevel error -filter_complex "$six" \
-c:a "$codec" -y "$work/six.$ext"
./audio_transfer_sniff_test --file "$work/six.$ext" "$type" --tones
done
# ATRAC3 and ATRAC3plus - stereo, joint stereo, mono, 4.0, 5.1,
# 6.1, 7.1 - in WAVE and OpenMG files the sample writes: FFmpeg
# decodes each to the samples audio_transfer gives (in FFmpeg's
# channel layout), and ffprobe reads the OpenMG ea3 tags as rtags
# does
- name: Decode audio_transfer's ATRAC files with FFmpeg
if: matrix.group == 'formats'
shell: bash
working-directory: libretro-common/samples/formats
run: |
set -euo pipefail
make -C audio_transfer_atrac -j2 SANITIZER=address,undefined
make -C tags -j2 SANITIZER=address,undefined
work=$(mktemp -d)
trap 'rm -rf "$work"' EXIT
./audio_transfer_atrac/audio_transfer_atrac_test --write "$work"
n=0
for f in "$work"/*.wav "$work"/*.oma; do
ffmpeg -nostdin -hide_banner -loglevel fatal -i "$f" -f f32le -y "$f.f32"
./audio_transfer_atrac/audio_transfer_atrac_test --compare "$f" "$f.f32"
n=$((n+1))
done
[ "$n" = 11 ]
for f in "$work"/*.oma; do
ffprobe -v error -show_entries format_tags:stream_tags \
-of default=nw=1 "$f" > "$f.tags"
./tags/rtags_test --ffprobe "$f" "$f.tags"
done
# AVI (MPEG-4 Part 2 with MP3, AVC with AC-3, MPEG-4 alone,
# MS-MPEG4 with PCM) and WMV (WMV2 with WMA2) from FFmpeg: rcontainer
# reads the streams, tags, sizes, rates, bit rates and length as
# ffprobe does
- name: Read FFmpeg's AVI and ASF headers with rcontainer
if: matrix.group == 'formats'
shell: bash
working-directory: libretro-common/samples/formats/container
run: |
set -euo pipefail
make -j2 SANITIZER=address,undefined
work=$(mktemp -d)
trap 'rm -rf "$work"' EXIT
v=(-f lavfi -i testsrc2=s=96x64:r=25:d=1)
a=(-f lavfi -i sine=f=440:d=1:sample_rate=44100)
ff() { ffmpeg -nostdin -hide_banner -loglevel error "$@"; }
ff "${v[@]}" "${a[@]}" -c:v mpeg4 -vtag XVID -c:a libmp3lame -y "$work/a.avi"
ff "${v[@]}" "${a[@]}" -c:v libx264 -c:a ac3 -y "$work/b.avi"
ff "${v[@]}" -c:v mpeg4 -y "$work/c.avi"
ff "${v[@]}" "${a[@]}" -c:v msmpeg4 -c:a pcm_s16le -ac 1 -y "$work/d.avi"
ff "${v[@]}" "${a[@]}" -c:v wmv2 -c:a wmav2 -y "$work/e.wmv"
n=0
for f in "$work"/*.avi "$work"/*.wmv; do
ffprobe -v error -show_entries \
stream=codec_type,codec_tag,width,height,sample_rate,channels,bit_rate,duration \
-of default=nw=1 "$f" > "$f.probe"
./rcontainer_test --ffprobe "$f" "$f.probe"
n=$((n+1))
done
[ "$n" = 5 ]
# RGBA to 4:2:0 against swscale's with the same 2x2 chroma average
# (area): every sample within 1, in each of FFmpeg's test patterns
- name: Convert RGBA to yuv420p as swscale does
if: matrix.group == 'formats'
shell: bash
working-directory: libretro-common/samples/formats/image_yuv
run: |
set -euo pipefail
work=$(mktemp -d)
trap 'rm -rf "$work"' EXIT
for src in testsrc2=size=160x120 smptehdbars=size=320x180 \
"gradients=size=256x144:speed=0.05" mandelbrot=size=200x150; do
ffmpeg -nostdin -hide_banner -loglevel error -f lavfi -i "$src:rate=25" \
-frames:v 8 -pix_fmt rgba -f rawvideo -y "$work/f.rgba"
size=$(ffprobe -v error -f lavfi -i "$src:rate=25" -show_entries stream=width,height \
-of csv=p=0 | head -1)
ffmpeg -nostdin -hide_banner -loglevel error -f rawvideo -pix_fmt rgba \
-s "${size/,/x}" -i "$work/f.rgba" -sws_flags area+accurate_rnd \
-pix_fmt yuv420p -f rawvideo -y "$work/f.yuv"
./image_yuv_test --ffmpeg "$work/f.rgba" "$work/f.yuv" ${size/,/ }
done
- name: Frontend H.264 decode interface, v1 to v4, plain and under ASan/UBSan
if: matrix.group == 'codecs'
shell: bash
@@ -1373,20 +841,6 @@ jobs:
TSAN_OPTIONS=halt_on_error=1 ./retro_atomic_test
- name: Run r7z_peek_threads_test under Clang + ThreadSanitizer
if: matrix.group == 'core'
shell: bash
working-directory: libretro-common/samples/formats/r7z
run: |
# A folder peeked at while another thread decodes it, through
# its being held: never torn, never the other folder's.
set -u
set -o pipefail
make clean
CC=clang make -j$(nproc) r7z_peek_threads_test SANITIZER=thread
TSAN_OPTIONS=halt_on_error=1 ./r7z_peek_threads_test
- name: Run video_player_test under Clang + ThreadSanitizer, and threadless
if: matrix.group == 'core'
shell: bash
@@ -1458,22 +912,6 @@ jobs:
TSAN_OPTIONS=halt_on_error=1 ./audio_mixer_voice_threads_test
# Every 16-bit sample through convert_s16_to_ulaw against FFmpeg's
# pcm_mulaw: all 65536 codes the same
- name: Encode mu-law as FFmpeg's pcm_mulaw does
if: matrix.group == 'core'
shell: bash
working-directory: libretro-common/samples/audio/float_to_ulaw
run: |
set -euo pipefail
work=$(mktemp -d)
trap 'rm -rf "$work"' EXIT
make -j2 all
./float_to_ulaw_test --ramp "$work/ramp.s16"
ffmpeg -nostdin -hide_banner -loglevel error -f s16le -ar 8000 -ac 1 \
-i "$work/ramp.s16" -c:a pcm_mulaw -f mulaw -y "$work/ramp.ul"
./float_to_ulaw_test --ffmpeg "$work/ramp.ul"
- name: Run mpsc_stack_test under Clang + ThreadSanitizer
if: matrix.group == 'core'
shell: bash
@@ -1982,34 +1420,6 @@ jobs:
-lwinmm -o thread_cleanup_test.exe
timeout 30 wine ./thread_cleanup_test.exe
- name: rtt under Wine
shell: bash
working-directory: libretro-common/samples/gfx/font
env:
WINEDEBUG: -all
run: |
set -eu
. "$GITHUB_WORKSPACE/.github/workflows/scripts/wine-server.sh"
make clean
make CC=x86_64-w64-mingw32-gcc all
timeout 60 wine ./rtt_test.exe
make clean
- name: socket_poll past FD_SETSIZE under Wine
shell: bash
working-directory: libretro-common/samples/net/socket_poll
env:
WINEDEBUG: -all
run: |
set -eu
. "$GITHUB_WORKSPACE/.github/workflows/scripts/wine-server.sh"
# select() takes 64 sockets a set; past that the sets are sized
# for the call.
make clean
make CC=x86_64-w64-mingw32-gcc all
timeout 60 wine ./socket_poll_test.exe
make clean
- name: Build and run the NVIDIA loaders under Wine
shell: bash
working-directory: libretro-common/samples/gfx/nvidia
-16
View File
@@ -64,15 +64,6 @@ jobs:
run: python3 samples/menu/rgui_media/run.py --c89 --cadence-hz 30 --driver materialui samples/menu/rgui_media/fixture.mp4
- name: Real XMB file-browser playback controls
run: python3 samples/menu/rgui_media/run.py --c89 --cadence-hz 30 --driver xmb samples/menu/rgui_media/fixture.mp4
- name: QuickTime MOV browsing and external launch across all menus
run: |
ffmpeg -v error -y -i samples/menu/rgui_media/fixture.mp4 -map 0 -c copy -f mov samples/menu/rgui_media/fixture.mov
python3 -c "import json,subprocess; p='samples/menu/rgui_media/fixture.mov'; d=json.loads(subprocess.check_output(['ffprobe','-v','error','-show_format','-of','json',p])); assert d['format']['tags']['major_brand']=='qt '"
cp samples/menu/rgui_media/fixture.mov samples/menu/rgui_media/fixture-upper.MOV
for driver in rgui materialui xmb ozone; do
python3 samples/menu/rgui_media/run.py --c89 --driver "$driver" samples/menu/rgui_media/fixture.mov
python3 samples/menu/rgui_media/run.py --c89 --external --driver "$driver" samples/menu/rgui_media/fixture-upper.MOV
done
- name: Real Ozone file-browser playback controls
run: python3 samples/menu/rgui_media/run.py --c89 --cadence-hz 30 --driver ozone samples/menu/rgui_media/fixture.mp4
- name: UTF-8 subtitle sidecars across all four menus
@@ -197,13 +188,6 @@ jobs:
xvfb-run -a python3 samples/menu/rgui_media/run.py --c89 --continuous-error --video-driver gl --driver "$driver" $threaded samples/menu/rgui_media/window-toggle.webm
done
done
- name: External movie settings retain the playing preview
run: |
for driver in materialui xmb ozone; do
for threaded in '' --threaded; do
MEDIA_TEST_SETTINGS_ORANGE=1 xvfb-run -a python3 samples/menu/rgui_media/run.py --c89 --external --external-settings --video-driver gl --driver "$driver" $threaded samples/menu/rgui_media/settings-preview.webm
done
done
- name: Generate delayed first-picture fixture
run: ffmpeg -v error -y -f lavfi -i "testsrc2=size=320x240:rate=30,hue=h=90*t" -vf "setpts=PTS+0.2/TB" -t 3 -c:v libvpx -deadline realtime -cpu-used 8 -g 90 -auto-alt-ref 0 samples/menu/rgui_media/delayed.webm
- name: Compare actual visible pictures after delayed-start seeks
@@ -87,22 +87,10 @@ jobs:
# IP address matches only an iPAddress SAN entry, never the
# same address written as a DNS name.
samples/network/tls_retro/local_server_test.sh
# One connection read and written from two threads at once
# (SSL_RETRO_DUPLEX), under ThreadSanitizer
make -C samples/network/tls_retro clean
make -C samples/network/tls_retro tls_duplex CFLAGS='-O1 -g -fsanitize=thread -fno-omit-frame-pointer'
TLS_TEST_DUPLEX_ONLY=1 TSAN_OPTIONS=halt_on_error=1 RUNNER="setarch $(uname -m) -R" \
samples/network/tls_retro/local_server_test.sh
# The same tool cross-linked for Windows: the sample's link
# line has to carry Winsock, which nothing on Linux checks.
make -C samples/network/tls_retro clean
- name: Incremental built-in TLS handshakes
shell: bash
run: |
set -eu
TLS_TEST_HANDSHAKE_STEP=1 samples/network/tls_retro/local_server_test.sh
make -C samples/network/tls_retro clean
- name: Built-in SMB2/3 client against a local smbd
shell: bash
-20
View File
@@ -1265,26 +1265,6 @@ jobs:
make clean
echo "[pass] udev_devices_test (ASan)"
- name: Build and run udev_touch_test (ASan + UBSan)
shell: bash
working-directory: samples/input/udev_touch
run: |
set -eu
# The udev input driver's touchscreen support
# (UDEV_TOUCH_SUPPORT), handed a panel in memory: its
# ioctls are answered by the test and evdev frames are fed
# to its event handler. The pointer is pressed while any
# contact is down and released after the last; the pointer
# device answers X, Y and pressed; a multi-touch panel's
# single-touch emulation leaves the slots alone; a
# single-touch panel's contact is slot 0; positions are
# taken from the axis minimum.
make clean SANITIZER=address,undefined && make -j$(nproc) all SANITIZER=address,undefined
ASAN_OPTIONS=detect_leaks=1 UBSAN_OPTIONS=print_stacktrace=1:halt_on_error=1 \
timeout 60 ./udev_touch_test
make clean
echo "[pass] udev_touch_test (ASan)"
- name: Build and run device_pins_test
shell: bash
working-directory: samples/input/device_pins
+2 -157
View File
@@ -7,10 +7,6 @@ on:
paths:
- 'record/**'
- 'libretro-common/net/net_rtmp*'
- 'libretro-common/net/net_socket.c'
- 'libretro-common/net/net_resolve.c'
- 'libretro-common/include/net/net_resolve.h'
- 'libretro-common/include/net/net_socket.h'
- 'libretro-common/include/net/net_rtmp*'
- 'libretro-common/formats/flv/**'
- 'libretro-common/include/formats/rflv_mux.h'
@@ -28,10 +24,6 @@ on:
paths:
- 'record/**'
- 'libretro-common/net/net_rtmp*'
- 'libretro-common/net/net_socket.c'
- 'libretro-common/net/net_resolve.c'
- 'libretro-common/include/net/net_resolve.h'
- 'libretro-common/include/net/net_socket.h'
- 'libretro-common/include/net/net_rtmp*'
- 'libretro-common/formats/flv/**'
- 'libretro-common/include/formats/rflv_mux.h'
@@ -60,7 +52,7 @@ jobs:
name: Build and run samples/record
runs-on: ubuntu-latest
env:
APT_PKGS: clang mingw-w64 wine build-essential pkg-config ffmpeg openssl python3 libavcodec-dev libavformat-dev libavutil-dev libswscale-dev libswresample-dev ccache
APT_PKGS: mingw-w64 wine build-essential pkg-config ffmpeg libavcodec-dev libavformat-dev libavutil-dev libswscale-dev libswresample-dev ccache
timeout-minutes: 25
steps:
@@ -149,8 +141,6 @@ jobs:
make clean && make check CC=x86_64-w64-mingw32-gcc EXE=.exe RUNNER=wine
make clean
- name: Native MP4 mux (ASan + UBSan, mingw-w64)
shell: bash
working-directory: samples/record/mp4_mux
@@ -171,73 +161,14 @@ jobs:
make clean && make check stream-check CC=x86_64-w64-mingw32-gcc EXE=.exe RUNNER=wine
make clean
- name: Media Foundation AAC portable and cross builds
shell: bash
working-directory: samples/record/mf_audio
run: |
set -eu
make clean all SANITIZER=address,undefined
make clean all CC=x86_64-w64-mingw32-gcc EXE=.exe
x86_64-w64-mingw32-objdump -p encode_test.exe > imports.txt
if grep -Ei 'DLL Name:.*(mfplat|mfaacenc|ole32)\.dll' imports.txt; then
echo 'Native AAC must load optional entry points at runtime'
exit 1
fi
make clean
- name: Pollable producer wake (Clang ASan + UBSan, mingw-w64)
shell: bash
working-directory: libretro-common/samples/net/wake
run: |
set -eu
. "$GITHUB_WORKSPACE/.github/workflows/scripts/wine-server.sh"
make clean && make check CC=clang SANITIZER=address,undefined
make clean && make check CC=x86_64-w64-mingw32-gcc EXE=.exe RUNNER=wine
make clean
- name: RTMP protocol and sockets (ASan + UBSan, TSan, mingw-w64)
- name: RTMP protocol and sockets (ASan + UBSan, mingw-w64)
shell: bash
working-directory: libretro-common/samples/net/rtmp
run: |
set -eu
. "$GITHUB_WORKSPACE/.github/workflows/scripts/wine-server.sh"
make clean && make rtmp_handshake_test CC=clang SANITIZER=address,undefined
./rtmp_handshake_test
make clean && make check peer-check SANITIZER=address,undefined
make rtmps_socket_native_test SANITIZER=address,undefined
python3 media_peer.py --mux --tls 1.2 ./rtmps_socket_native_test
python3 media_peer.py --mux --tls 1.3 ./rtmps_socket_native_test
make rtmps_client_native_test SANITIZER=address,undefined
python3 media_peer.py --caps --mux --tls 1.2 ./rtmps_client_native_test
python3 media_peer.py --caps --mux --tls 1.3 ./rtmps_client_native_test
python3 media_peer.py --codec av1 --caps --mux --tls 1.2 ./rtmps_client_native_test
python3 media_peer.py --codec av1 --caps --mux --tls 1.3 ./rtmps_client_native_test
python3 media_peer.py --codec hevc --caps --mux --tls 1.2 ./rtmps_client_native_test
python3 media_peer.py --codec hevc --caps --mux --tls 1.3 ./rtmps_client_native_test
make clean && make rtmp_resolve_native_test SANITIZER=thread
TSAN_OPTIONS=halt_on_error=1 timeout 30 ./rtmp_resolve_native_test
make clean && make check peer-check CC=x86_64-w64-mingw32-gcc EXE=.exe RUNNER=wine
make rtmps_socket_native_test.exe CC=x86_64-w64-mingw32-gcc EXE=.exe
python3 media_peer.py --runner wine --mux --tls 1.2 ./rtmps_socket_native_test.exe
python3 media_peer.py --runner wine --mux --tls 1.3 ./rtmps_socket_native_test.exe
make rtmps_client_native_test.exe CC=x86_64-w64-mingw32-gcc EXE=.exe
python3 media_peer.py --runner wine --caps --mux --tls 1.2 ./rtmps_client_native_test.exe
python3 media_peer.py --runner wine --caps --mux --tls 1.3 ./rtmps_client_native_test.exe
python3 media_peer.py --runner wine --codec av1 --caps --mux --tls 1.2 ./rtmps_client_native_test.exe
python3 media_peer.py --runner wine --codec av1 --caps --mux --tls 1.3 ./rtmps_client_native_test.exe
python3 media_peer.py --runner wine --codec hevc --caps --mux --tls 1.2 ./rtmps_client_native_test.exe
python3 media_peer.py --runner wine --codec hevc --caps --mux --tls 1.3 ./rtmps_client_native_test.exe
make clean
- name: Native encoder stream ownership contracts
working-directory: samples/record/rtmp_stream
run: |
set -eu
. "$GITHUB_WORKSPACE/.github/workflows/scripts/wine-server.sh"
make clean check SANITIZER=address,undefined
make clean vt_thread_test SANITIZER=thread
TSAN_OPTIONS=halt_on_error=1 timeout 120 ./vt_thread_test
make clean check CC=x86_64-w64-mingw32-gcc EXE=.exe RUNNER=wine
make clean
- name: GPU PCM output pipeline (ASan + UBSan, TSan, mingw-w64)
@@ -277,16 +208,6 @@ jobs:
make clean && make check CC=x86_64-w64-mingw32-gcc EXE=.exe RUNNER=wine
make clean
- name: AudioToolbox AAC input and packet ownership contracts
working-directory: samples/record/audiotoolbox_audio
run: |
set -eu
. "$GITHUB_WORKSPACE/.github/workflows/scripts/wine-server.sh"
make clean && make check CC=clang
make clean && make check SANITIZER=address,undefined
make clean && make check CC=x86_64-w64-mingw32-gcc EXE=.exe RUNNER=wine
make clean
# The Apple API stand-in checks ownership/configuration only. Native
# compilation and hardware encode run in MacOS-videotoolbox-encode.yml.
- name: VideoToolbox encode callback and session contracts
@@ -320,79 +241,3 @@ jobs:
with:
path: ~/.ccache
key: ccache-${{ github.workflow }}-${{ github.job }}-${{ github.sha }}
mf-audio-native:
name: Native Windows AAC packets and source clock
runs-on: windows-latest
timeout-minutes: 15
steps:
- name: Checkout
uses: actions/checkout@v5
- name: Ensure the server media component is installed
shell: pwsh
run: |
if ((Get-CimInstance Win32_OperatingSystem).ProductType -ne 1) {
$feature = Get-WindowsFeature Server-Media-Foundation -ErrorAction Stop
if (-not $feature.Installed) {
$result = Install-WindowsFeature Server-Media-Foundation -ErrorAction Stop
if (-not $result.Success) { throw 'Media Foundation installation failed' }
}
}
- name: Native compiler and independent decoder
uses: msys2/setup-msys2@v2
with:
msystem: MINGW64
update: false
install: make mingw-w64-x86_64-gcc mingw-w64-x86_64-python mingw-w64-x86_64-ffmpeg
- name: Encode and independently decode native AAC
shell: msys2 {0}
working-directory: samples/record/mf_audio
run: |
set -eu
make clean native-check CC=gcc EXE=.exe
objdump -p encode_test.exe > imports.txt
if grep -Ei 'DLL Name:.*(mfplat|mfaacenc|ole32)\.dll' imports.txt; then
echo 'Native AAC must load optional entry points at runtime'
exit 1
fi
make clean
- name: Native Metal frontend profiles and source clocks
shell: msys2 {0}
working-directory: samples/record/metal_frontend
run: |
set -eu
make clean
make check CC=gcc EXE=.exe
make clean
- name: Config include ownership and stack budget
shell: msys2 {0}
working-directory: libretro-common/samples/file/config_file
run: |
set -eu
make clean
make check CC=gcc EXE=.exe
make clean CC=gcc EXE=.exe
- name: Native streaming worker readiness and cancellation
shell: msys2 {0}
working-directory: samples/record/gpu_dispatch
run: |
set -eu
make clean
make stream_dispatch_test.exe CC=gcc EXE=.exe
./stream_dispatch_test.exe
make clean
- name: Native FLV source color metadata interoperability
shell: msys2 {0}
working-directory: libretro-common/samples/formats/flv
run: |
set -eu
make clean
make check stream-check CC=gcc EXE=.exe COLOR_METADATA_ORACLE=1
make clean
@@ -958,14 +958,6 @@ jobs:
python3 samples/menu/rgui_media/run.py --driver rgui --video-driver ${{ matrix.driver }} --gpu-surface --refresh-pixels samples/menu/rgui_media/fixture.mp4
python3 samples/menu/rgui_media/run.py --driver rgui --video-driver ${{ matrix.driver }} --gpu-surface --continuous-error samples/menu/rgui_media/fixture.mp4
- name: External Ozone movie settings at drive root and in a subfolder
if: matrix.driver == 'd3d11'
shell: msys2 {0}
run: |
set -eu
ffmpeg -v error -y -f lavfi -i color=orange:size=320x240:rate=30 -t 3 -c:v libx264 -preset ultrafast -pix_fmt yuv420p samples/menu/rgui_media/settings-preview.mp4
MEDIA_TEST_SETTINGS_ORANGE=1 python3 samples/menu/texture_media/external_settings_paths.py samples/menu/rgui_media/settings-preview.mp4 --video-driver ${{ matrix.driver }} --threaded
views-sdl3:
name: Views on SDL3, end to end (Xvfb, llvmpipe)
runs-on: ubuntu-latest
-18
View File
@@ -56,24 +56,6 @@ jobs:
uses: actions/checkout@v5
- name: Set up MSYS2
id: msys2
continue-on-error: true
uses: msys2/setup-msys2@v2
with:
msystem: ${{ matrix.sys }}
update: true
# setup-msys2 has no retry of its own, and its system upgrade fails
# the job when mirror.msys2.org stalls ("Operation too slow") on the
# package databases. A failed attempt is run once more after a
# minute; the second reinstalls over the first.
- name: Wait before retrying MSYS2
if: steps.msys2.outcome == 'failure'
shell: bash
run: sleep 60
- name: Set up MSYS2 (retry)
if: steps.msys2.outcome == 'failure'
uses: msys2/setup-msys2@v2
with:
msystem: ${{ matrix.sys }}
@@ -17,21 +17,7 @@ on:
- 'record/record_gpu_session_metal.*'
- 'record/record_gpu_dispatch_metal.*'
- 'record/record_gpu_worker_vt*'
- 'record/record_vt_packet.*'
- 'record/record_stream_vt.*'
- 'record/record_stream_output_vt.*'
- 'record/record_stream_session_vt_native.h'
- 'samples/record/rtmp_stream/**'
- 'libretro-common/net/net_rtmp*'
- 'libretro-common/include/net/net_rtmp*'
- 'libretro-common/formats/flv/**'
- 'libretro-common/include/formats/rflv_mux.h'
- 'libretro-common/include/formats/rav1_sequence.h'
- 'libretro-common/include/formats/video_color.h'
- 'record/record_audio_queue.*'
- 'record/record_at_audio.*'
- 'record/record_at_resample.*'
- 'samples/record/audiotoolbox_audio/**'
- 'record/record_avfoundation_worker*'
- 'record/record_avfoundation_session*'
- 'record/record_mux_avfoundation.*'
@@ -56,21 +42,7 @@ on:
- 'record/record_gpu_session_metal.*'
- 'record/record_gpu_dispatch_metal.*'
- 'record/record_gpu_worker_vt*'
- 'record/record_vt_packet.*'
- 'record/record_stream_vt.*'
- 'record/record_stream_output_vt.*'
- 'record/record_stream_session_vt_native.h'
- 'samples/record/rtmp_stream/**'
- 'libretro-common/net/net_rtmp*'
- 'libretro-common/include/net/net_rtmp*'
- 'libretro-common/formats/flv/**'
- 'libretro-common/include/formats/rflv_mux.h'
- 'libretro-common/include/formats/rav1_sequence.h'
- 'libretro-common/include/formats/video_color.h'
- 'record/record_audio_queue.*'
- 'record/record_at_audio.*'
- 'record/record_at_resample.*'
- 'samples/record/audiotoolbox_audio/**'
- 'record/record_avfoundation_worker*'
- 'record/record_avfoundation_session*'
- 'record/record_mux_avfoundation.*'
@@ -80,115 +52,10 @@ on:
- 'samples/record/metal_frontend/**'
- 'libretro-common/include/retro_atomic.h'
workflow_dispatch:
inputs:
ios_sdk_only:
description: 'Audit production VideoToolbox declarations against real iOS SDKs'
type: boolean
default: false
native_aac_only:
description: 'Run native AudioToolbox AAC acceptance without GPU/frontend jobs'
type: boolean
default: false
frontend_stream_only:
description: 'Run frontend streaming acceptance and both native frontend links'
type: boolean
default: false
permissions:
contents: read
jobs:
stream-native:
if: ${{ !inputs.ios_sdk_only && !inputs.native_aac_only && !inputs.frontend_stream_only }}
runs-on: macos-latest
timeout-minutes: 10
steps:
- uses: actions/checkout@v6
- name: Install independent streaming receiver
run: command -v ffmpeg >/dev/null && command -v ffprobe >/dev/null || brew install ffmpeg
- name: Pollable producer wake and socket readiness
run: make -C libretro-common/samples/net/wake check
- name: Native VT and AAC over RTMP and TLS
env:
VT_STREAM_ARTIFACT_DIR: ${{ runner.temp }}/vt-stream-evidence
run: python3 samples/record/rtmp_stream/native_vt_run.py
- name: Save native streaming acceptance evidence
if: ${{ always() }}
uses: actions/upload-artifact@v4
with:
name: vt-stream-evidence
path: ${{ runner.temp }}/vt-stream-evidence
if-no-files-found: ignore
- name: Native Metal factory RTMP and TLS with ARC
if: ${{ !cancelled() }}
env:
VT_STREAM_ARTIFACT_DIR: ${{ runner.temp }}/vt-metal-stream-arc
run: python3 samples/record/rtmp_stream/native_vt_run.py --metal --ownership arc
- name: Native Metal factory RTMP and TLS with manual reference counting
if: ${{ !cancelled() }}
env:
VT_STREAM_ARTIFACT_DIR: ${{ runner.temp }}/vt-metal-stream-mrc
run: python3 samples/record/rtmp_stream/native_vt_run.py --metal --ownership mrc
- name: Save native Metal streaming acceptance evidence
if: ${{ always() }}
uses: actions/upload-artifact@v4
with:
name: vt-metal-stream-evidence
path: |
${{ runner.temp }}/vt-metal-stream-arc
${{ runner.temp }}/vt-metal-stream-mrc
if-no-files-found: ignore
- name: Native URL-owning Metal streaming dispatcher with ARC
if: ${{ !cancelled() }}
env:
VT_STREAM_ARTIFACT_DIR: ${{ runner.temp }}/vt-metal-dispatch-arc
run: python3 samples/record/rtmp_stream/native_vt_run.py --dispatcher --ownership arc
- name: Native URL-owning Metal streaming dispatcher with manual reference counting
if: ${{ !cancelled() }}
env:
VT_STREAM_ARTIFACT_DIR: ${{ runner.temp }}/vt-metal-dispatch-mrc
run: python3 samples/record/rtmp_stream/native_vt_run.py --dispatcher --ownership mrc
- name: Save native Metal dispatcher acceptance evidence
if: ${{ always() }}
uses: actions/upload-artifact@v4
with:
name: vt-metal-dispatch-evidence
path: |
${{ runner.temp }}/vt-metal-dispatch-arc
${{ runner.temp }}/vt-metal-dispatch-mrc
if-no-files-found: ignore
aac-native:
if: ${{ !inputs.ios_sdk_only && (inputs.native_aac_only || !inputs.frontend_stream_only) }}
runs-on: macos-latest
timeout-minutes: 10
steps:
- uses: actions/checkout@v6
- name: Install independent AAC test decoder
run: command -v ffmpeg >/dev/null || brew install ffmpeg
- name: AudioToolbox AAC callback ownership contracts
run: make -C samples/record/audiotoolbox_audio check
- name: Native AudioToolbox AAC packets and independent timing
env:
AUDIO_TOOLBOX_ARTIFACT_DIR: ${{ runner.temp }}/audiotoolbox-aac-evidence
run: make -C samples/record/audiotoolbox_audio native-check
- name: Save AudioToolbox AAC acceptance evidence
if: ${{ always() }}
uses: actions/upload-artifact@v4
with:
name: audiotoolbox-aac-evidence
path: ${{ runner.temp }}/audiotoolbox-aac-evidence
if-no-files-found: ignore
- name: Native source-rate conversion and independent AAC timing
env:
AUDIO_TOOLBOX_SRC_ARTIFACT_DIR: ${{ runner.temp }}/audiotoolbox-src-evidence
run: make -C samples/record/audiotoolbox_audio native-src-check
- name: Save AudioToolbox SRC acceptance evidence
if: ${{ always() }}
uses: actions/upload-artifact@v4
with:
name: audiotoolbox-src-evidence
path: ${{ runner.temp }}/audiotoolbox-src-evidence
if-no-files-found: ignore
encode:
if: ${{ !inputs.ios_sdk_only && !inputs.native_aac_only && !inputs.frontend_stream_only }}
runs-on: macos-latest
timeout-minutes: 20
steps:
@@ -201,8 +68,6 @@ jobs:
- name: Portable ownership and failure contracts
working-directory: samples/record/videotoolbox_encode
run: make check thread_test worker_thread_test audio_thread_test av_session_thread_test && ./thread_test && ./worker_thread_test && ./audio_thread_test && ./av_session_thread_test
- name: VideoToolbox AAC streaming ownership and independent wire clock
run: make -C samples/record/rtmp_stream vt-check
- name: Native AAC property ABI and advertised rates
run: make -C samples/record/videotoolbox_encode native-audio-check
- name: Native hardware encoder and independent pixels
@@ -289,7 +154,6 @@ jobs:
if-no-files-found: warn
frontend-build:
if: ${{ !inputs.ios_sdk_only && !inputs.native_aac_only && !inputs.frontend_stream_only }}
runs-on: macos-latest
timeout-minutes: 40
steps:
@@ -325,97 +189,9 @@ jobs:
path: ${{ runner.temp }}/metal-frontend-recordings
if-no-files-found: warn
frontend-stream-build:
if: ${{ !inputs.ios_sdk_only && !inputs.native_aac_only }}
runs-on: macos-latest
timeout-minutes: 20
strategy:
fail-fast: false
matrix:
threads: [enable, disable]
steps:
- uses: actions/checkout@v6
- name: Configure network-enabled Metal frontend
run: |
set -eu
stream_options=
if [ "${{ matrix.threads }}" = disable ]; then
stream_options="--enable-rtmp --enable-rflv"
fi
./configure --enable-metal --enable-avf --${{ matrix.threads }}-threads --enable-configfile --enable-webmplayer \
--disable-qt --disable-ffmpeg --disable-discord --disable-cheevos \
--enable-networking --disable-sdl2 --disable-sdl --disable-translate \
--disable-update_cores --disable-update_assets --disable-online_updater \
--disable-cdrom --disable-7zip --enable-ssl --enable-retrossl $stream_options
for feature in HAVE_METAL HAVE_AVF HAVE_NETWORKING HAVE_CRYPTO HAVE_RTMP HAVE_RFLV HAVE_RETROSSL; do
grep -Eq "^#define $feature 1" config.h
done
- name: Link network worker and threadless fallback
run: |
set -eu
make -j"$(sysctl -n hw.ncpu)" \
MINVERFLAGS="-mmacosx-version-min=$(sw_vers -productVersion)"
test -x retroarch
nm retroarch | grep '_record_gpu_dispatch_metal_new_stream'
- name: Native frontend streaming through command start and stop
if: ${{ matrix.threads == 'enable' }}
run: |
set -eu
command -v ffmpeg >/dev/null && command -v ffprobe >/dev/null || brew install ffmpeg
cc -dynamiclib -std=gnu89 -Ilibretro-common/include samples/record/metal_frontend/core.c -o "$RUNNER_TEMP/metal-stream-core.dylib" -lm
python3 samples/record/metal_frontend/stream.py --retroarch ./retroarch --core "$RUNNER_TEMP/metal-stream-core.dylib" --video-buffer-frames 2 --output-dir "$RUNNER_TEMP/metal-frontend-stream/h264"
python3 samples/record/metal_frontend/stream.py --retroarch ./retroarch --core "$RUNNER_TEMP/metal-stream-core.dylib" --codec hevc --source-rate 32040.5 --video-buffer-frames 16 --output-dir "$RUNNER_TEMP/metal-frontend-stream/fractional"
python3 samples/record/metal_frontend/stream.py --retroarch ./retroarch --core "$RUNNER_TEMP/metal-stream-core.dylib" --channels 1 --source-rate 44100 --video-buffer-frames 8 --output-dir "$RUNNER_TEMP/metal-frontend-stream/mono"
python3 samples/record/metal_frontend/stream.py --retroarch ./retroarch --core "$RUNNER_TEMP/metal-stream-core.dylib" --video-only --video-buffer-frames 4 --output-dir "$RUNNER_TEMP/metal-frontend-stream/video-only"
- name: Save real frontend streaming evidence
if: ${{ always() && matrix.threads == 'enable' }}
uses: actions/upload-artifact@v4
with:
name: metal-frontend-stream-evidence
path: ${{ runner.temp }}/metal-frontend-stream
if-no-files-found: ignore
frontend-contracts:
if: ${{ !inputs.ios_sdk_only && !inputs.native_aac_only }}
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- name: Source-clock capture and backpressure under sanitizers
run: make -C samples/record/metal_frontend check SANITIZER=address,undefined
ios-sdk:
if: ${{ inputs.ios_sdk_only }}
runs-on: macos-latest
timeout-minutes: 10
steps:
- uses: actions/checkout@v6
- name: Compile production VideoToolbox headers for iOS and simulator
run: python3 samples/record/videotoolbox_encode/ios_sdk_check.py --output-dir "${{ runner.temp }}/vt-ios-sdk"
- name: Save actual SDK diagnostics
if: ${{ always() }}
uses: actions/upload-artifact@v4
with:
name: vt-ios-sdk
path: ${{ runner.temp }}/vt-ios-sdk
if-no-files-found: error
ios-app:
if: ${{ inputs.ios_sdk_only }}
needs: ios-sdk
runs-on: macos-latest
timeout-minutes: 60
steps:
- uses: actions/checkout@v6
- name: Build and link actual iOS application with native recording
run: python3 samples/record/videotoolbox_encode/ios_app_check.py --output-dir "${{ runner.temp }}/vt-ios-app"
- name: Save full application build evidence
if: ${{ always() }}
uses: actions/upload-artifact@v4
with:
name: vt-ios-app
path: |
${{ runner.temp }}/vt-ios-app/*.json
${{ runner.temp }}/vt-ios-app/*.log
${{ runner.temp }}/vt-ios-app/*.txt
${{ runner.temp }}/vt-ios-app/build.xcresult
if-no-files-found: error
+1 -1
View File
@@ -1082,7 +1082,7 @@ check_gates "griffin: HAVE_RETROSMB + cloud sync" "$UIDEFS -DRARCH_INTERNAL -DH
# griffin can carry. A static helper in one translation unit that
# another one also defines (get32 in net_smb2.c and rvorbis.c) only
# collides here, so this lane carries as much of griffin as a host can.
GRIFFIN_FULL="-DRARCH_INTERNAL -DHAVE_GRIFFIN=1 -DHAVE_MENU -DHAVE_RGUI -DHAVE_XMB -DHAVE_OZONE -DHAVE_MATERIALUI -DHAVE_GFX_WIDGETS -DHAVE_OVERLAY -DHAVE_CONFIGFILE -DHAVE_CHEEVOS -DRC_DISABLE_LUA -DHAVE_RUNAHEAD -DHAVE_REWIND -DHAVE_PATCH -DHAVE_XDELTA -DHAVE_CHEATS -DHAVE_SCREENSHOTS -DHAVE_TRANSLATE -DHAVE_LIBRETRODB -DHAVE_DYNAMIC -DHAVE_DYLIB -DHAVE_THREADS -DHAVE_AUDIOMIXER -DHAVE_DSP_FILTER -DHAVE_VIDEO_FILTER -DHAVE_RWAV -DHAVE_RFLAC -DHAVE_RVORBIS -DHAVE_RMP3 -DHAVE_RAC3 -DHAVE_RPNG -DHAVE_RJPEG -DHAVE_RBMP -DHAVE_RTGA -DHAVE_RGIF -DHAVE_RWEBP -DHAVE_RDDS -DHAVE_RZSTD -DHAVE_7ZIP -DHAVE_CHD -DHAVE_RCHD -DHAVE_STB_FONT -DHAVE_NETWORKING -DHAVE_IFINFO -DHAVE_NETWORK_CMD -DHAVE_NETPLAYDISCOVERY -DHAVE_ONLINE_UPDATER -DHAVE_UPDATE_ASSETS -DHAVE_UPDATE_CORES -DHAVE_UPDATE_CORE_INFO -DHAVE_CORE_INFO_CACHE -DHAVE_CLOUDSYNC -DHAVE_S3 -DHAVE_CRYPTO -DHAVE_KEYCHAIN -DHAVE_SSL -DHAVE_RETROSSL -DHAVE_SMBCLIENT -DHAVE_RETROSMB -DHAVE_NFSCLIENT -DHAVE_RETRONFS -DHAVE_LANGEXTRA -DHAVE_SHADERPIPELINE -DHAVE_GLSL -DHAVE_OPENGL -D_GNU_SOURCE"
GRIFFIN_FULL="-DRARCH_INTERNAL -DHAVE_GRIFFIN=1 -DHAVE_MENU -DHAVE_RGUI -DHAVE_XMB -DHAVE_OZONE -DHAVE_MATERIALUI -DHAVE_GFX_WIDGETS -DHAVE_OVERLAY -DHAVE_CONFIGFILE -DHAVE_CHEEVOS -DRC_DISABLE_LUA -DHAVE_RUNAHEAD -DHAVE_REWIND -DHAVE_PATCH -DHAVE_XDELTA -DHAVE_CHEATS -DHAVE_SCREENSHOTS -DHAVE_TRANSLATE -DHAVE_LIBRETRODB -DHAVE_DYNAMIC -DHAVE_DYLIB -DHAVE_THREADS -DHAVE_AUDIOMIXER -DHAVE_DSP_FILTER -DHAVE_VIDEO_FILTER -DHAVE_RWAV -DHAVE_RFLAC -DHAVE_RVORBIS -DHAVE_RMP3 -DHAVE_RAC3 -DHAVE_RPNG -DHAVE_RJPEG -DHAVE_RBMP -DHAVE_RTGA -DHAVE_RWEBP -DHAVE_RDDS -DHAVE_RZSTD -DHAVE_7ZIP -DHAVE_CHD -DHAVE_RCHD -DHAVE_STB_FONT -DHAVE_NETWORKING -DHAVE_IFINFO -DHAVE_NETWORK_CMD -DHAVE_NETPLAYDISCOVERY -DHAVE_ONLINE_UPDATER -DHAVE_UPDATE_ASSETS -DHAVE_UPDATE_CORES -DHAVE_UPDATE_CORE_INFO -DHAVE_CORE_INFO_CACHE -DHAVE_CLOUDSYNC -DHAVE_S3 -DHAVE_CRYPTO -DHAVE_KEYCHAIN -DHAVE_SSL -DHAVE_RETROSSL -DHAVE_SMBCLIENT -DHAVE_RETROSMB -DHAVE_NFSCLIENT -DHAVE_RETRONFS -DHAVE_LANGEXTRA -DHAVE_SHADERPIPELINE -DHAVE_GLSL -DHAVE_OPENGL -D_GNU_SOURCE"
check_gates "griffin: full unity (every codec + network stack)" "$UIDEFS $GRIFFIN_FULL" griffin/griffin.c
# The SMB show-settings row read a HAVE_MENU-only default under
# HAVE_SMBCLIENT alone; with the built-in client on by default that
-1
View File
@@ -403,4 +403,3 @@ samples/record/ffmpeg_pipeline/record_finalize_fragment.c
samples/record/ffmpeg_pipeline/record_start_fragment.c
samples/input/sensor_subdevice/core_sensor_fragment.c
samples/input/bind_capture/driver_code.inc
samples/record/metal_frontend/profile_fragment.c
+4 -38
View File
@@ -1126,8 +1126,7 @@ ifeq ($(HAVE_OVERLAY), 1)
led/drivers/led_overlay.o
endif
OBJ += gfx/drivers_font_renderer/stb.o \
$(LIBRETRO_COMM_DIR)/gfx/font/rtt.o
OBJ += gfx/drivers_font_renderer/stb.o
ifeq ($(HAVE_FREETYPE), 1)
OBJ += gfx/drivers_font_renderer/freetype.o
@@ -1704,17 +1703,6 @@ ifeq ($(HAVE_METAL), 1)
record/record_gpu_session_metal.o \
record/record_gpu_dispatch_metal.o \
$(LIBRETRO_COMM_DIR)/formats/h265/rh265_sps_crop.o
ifeq ($(HAVE_NETWORKING), 1)
ifeq ($(HAVE_RTMP), 1)
ifeq ($(HAVE_RFLV), 1)
OBJ += record/record_stream_vt.o \
record/record_stream_output_vt.o \
record/record_at_resample.o \
record/record_vt_packet.o \
$(LIBRETRO_COMM_DIR)/net/net_wake.o
endif
endif
endif
LIBS += -framework CoreMedia -framework VideoToolbox -framework AudioToolbox
endif
endif
@@ -2050,20 +2038,6 @@ ifeq ($(HAVE_D3D12), 1)
DEFINES += -DHAVE_D3D12
endif
ifeq ($(HAVE_MF_AUDIO), 1)
ifneq ($(findstring Win32,$(OS)),)
DEFINES += -DHAVE_MF_AUDIO
OBJ += record/record_mf_audio.o
ifeq ($(HAVE_RTMP), 1)
ifeq ($(HAVE_RFLV), 1)
ifeq ($(HAVE_D3D12), 1)
OBJ += record/record_stream_d3d12.o
endif
endif
endif
endif
endif
# H.264 previews decoded on the GPU, as rh264's backend; D3D12 imports
# its frames as well
ifneq ($(findstring 1, $(HAVE_D3D11) $(HAVE_D3D12)),)
@@ -2549,11 +2523,6 @@ ifeq ($(HAVE_RTGA), 1)
OBJ += $(LIBRETRO_COMM_DIR)/formats/tga/rtga.o
endif
ifeq ($(HAVE_RGIF), 1)
DEFINES += -DHAVE_RGIF
OBJ += $(LIBRETRO_COMM_DIR)/formats/gif/rgif.o
endif
ifeq ($(HAVE_RDDS), 1)
DEFINES += -DHAVE_RDDS
OBJ += $(LIBRETRO_COMM_DIR)/formats/dds/rdds.o
@@ -2695,11 +2664,10 @@ endif
# when HAVE_AVF is on.
ifeq ($(HAVE_AVF), 1)
DEFINES += -DHAVE_AVF
OBJ += record/record_at_audio.o \
camera/drivers/avfoundation.o \
OBJ += camera/drivers/avfoundation.o \
record/drivers/record_avfoundation.o
LIBS += -framework AVFoundation -framework CoreVideo \
-framework CoreMedia -framework Accelerate -framework AudioToolbox
-framework CoreMedia -framework Accelerate
ifeq ($(HAVE_COCOATOUCH), 1)
LIBS += -framework UIKit
endif
@@ -2792,14 +2760,12 @@ ifeq ($(HAVE_NETWORKING), 1)
$(LIBRETRO_COMM_DIR)/net/net_rtmp_receive.o \
$(LIBRETRO_COMM_DIR)/net/net_rtmp_reply.o \
$(LIBRETRO_COMM_DIR)/net/net_rtmp_session.o \
$(LIBRETRO_COMM_DIR)/net/net_rtmp_socket.o \
$(LIBRETRO_COMM_DIR)/net/net_rtmp_client.o
$(LIBRETRO_COMM_DIR)/net/net_rtmp_socket.o
endif
OBJ += $(LIBRETRO_COMM_DIR)/net/net_compat.o \
$(LIBRETRO_COMM_DIR)/net/net_http.o \
$(LIBRETRO_COMM_DIR)/net/net_http_parse.o \
$(LIBRETRO_COMM_DIR)/net/net_socket.o \
$(LIBRETRO_COMM_DIR)/net/net_resolve.o \
core_updater_list.o \
network/natt.o \
network/natt_desc.o \
+1 -2
View File
@@ -53,7 +53,7 @@ DEFINES :=
ifeq ($(GRIFFIN_BUILD), 1)
OBJ += griffin/griffin.o
DEFINES += -DHAVE_GRIFFIN=1 -DHAVE_MENU -DHAVE_CONFIGFILE -DHAVE_RGUI -DHAVE_XMB -DHAVE_LIBRETRODB -DHAVE_CC_RESAMPLER
DEFINES += -DHAVE_7ZIP -DHAVE_RZSTD -DHAVE_RPNG -DHAVE_RWEBP -DHAVE_RDDS -DHAVE_RJPEG -DHAVE_RBMP -DHAVE_RTGA -DHAVE_RGIF
DEFINES += -DHAVE_7ZIP -DHAVE_RZSTD -DHAVE_RPNG -DHAVE_RWEBP -DHAVE_RDDS -DHAVE_RJPEG -DHAVE_RBMP -DHAVE_RTGA
DEFINES += -DHAVE_NETWORKING -DHAVE_IFINFO -DHAVE_CHEEVOS -DRC_DISABLE_LUA -DHAVE_ONLINE_UPDATER -DHAVE_UPDATE_CORES
DEFINES += -DHAVE_UPDATE_CORE_INFO
#DEFINES += -DHAVE_UPDATE_ASSETS
@@ -73,7 +73,6 @@ else
HAVE_CC_RESAMPLER = 1
HAVE_MENU_COMMON = 1
HAVE_RTGA = 1
HAVE_RGIF = 1
HAVE_RPNG = 1
HAVE_RWEBP = 1
HAVE_RDDS = 1
-1
View File
@@ -34,7 +34,6 @@ HAVE_AUDIOMIXER = 1
HAVE_CC_RESAMPLER = 1
HAVE_MENU_COMMON = 1
HAVE_RTGA = 1
HAVE_RGIF = 1
HAVE_RPNG = 1
HAVE_RWEBP = 1
HAVE_RDDS = 1
-1
View File
@@ -34,7 +34,6 @@ HAVE_AUDIOMIXER = 1
HAVE_CC_RESAMPLER = 1
HAVE_MENU_COMMON = 1
HAVE_RTGA = 1
HAVE_RGIF = 1
HAVE_RPNG = 1
HAVE_RJPEG = 1
HAVE_RBMP = 1
-21
View File
@@ -196,7 +196,6 @@ else ifeq ($(libogc_platform), 1)
HAVE_RJPEG := 1
HAVE_RBMP := 1
HAVE_RTGA := 1
HAVE_RGIF := 1
HAVE_RMODTRACKER := 1
HAVE_OVERLAY := 1
HAVE_7ZIP := 1
@@ -273,7 +272,6 @@ else ifeq ($(platform), psp1)
HAVE_RJPEG := 1
HAVE_RBMP := 1
HAVE_RTGA := 1
HAVE_RGIF := 1
HAVE_KERNEL_PRX := 1
#HAVE_LANGEXTRA := 1
RARCH_CONSOLE = 1
@@ -326,7 +324,6 @@ else ifeq ($(platform), vita)
HAVE_RJPEG := 1
HAVE_RBMP := 1
HAVE_RTGA := 1
HAVE_RGIF := 1
HAVE_7ZIP := 1
HAVE_GXM := 1
HAVE_NETWORKING := 1
@@ -349,7 +346,6 @@ else ifeq ($(platform), windows_msvc6_x86)
HAVE_RJPEG := 1
HAVE_RBMP := 1
HAVE_RTGA := 1
HAVE_RGIF := 1
HAVE_7ZIP := 1
HAVE_NETWORKING := 0
HAVE_IFINFO := 0
@@ -401,7 +397,6 @@ else ifeq ($(platform), windows_msvc2003_x86)
HAVE_RJPEG := 1
HAVE_RBMP := 1
HAVE_RTGA := 1
HAVE_RGIF := 1
HAVE_7ZIP := 1
HAVE_NETWORKING := 1
HAVE_IFINFO := 0
@@ -459,7 +454,6 @@ else ifeq ($(platform), windows_msvc2005_x86)
HAVE_RJPEG := 1
HAVE_RBMP := 1
HAVE_RTGA := 1
HAVE_RGIF := 1
HAVE_7ZIP := 1
HAVE_NETWORKING := 1
HAVE_IFINFO := 0
@@ -548,7 +542,6 @@ else ifneq (,$(findstring windows_msvc2010,$(platform)))
HAVE_RJPEG := 1
HAVE_RBMP := 1
HAVE_RTGA := 1
HAVE_RGIF := 1
HAVE_7ZIP := 1
HAVE_NETWORKING := 1
HAVE_IFINFO := 1
@@ -645,7 +638,6 @@ else ifneq (,$(findstring windows_msvc2012,$(platform)))
HAVE_RJPEG := 1
HAVE_RBMP := 1
HAVE_RTGA := 1
HAVE_RGIF := 1
HAVE_7ZIP := 1
HAVE_NETWORKING := 1
HAVE_IFINFO := 1
@@ -733,7 +725,6 @@ else ifneq (,$(findstring windows_msvc2013,$(platform)))
HAVE_RJPEG := 1
HAVE_RBMP := 1
HAVE_RTGA := 1
HAVE_RGIF := 1
HAVE_7ZIP := 1
HAVE_NETWORKING := 1
HAVE_IFINFO := 1
@@ -821,7 +812,6 @@ else ifneq (,$(findstring windows_msvc2015,$(platform)))
HAVE_RJPEG := 1
HAVE_RBMP := 1
HAVE_RTGA := 1
HAVE_RGIF := 1
HAVE_7ZIP := 1
HAVE_NETWORKING := 1
HAVE_IFINFO := 1
@@ -924,7 +914,6 @@ else ifeq (qnx,$(platform))
HAVE_RJPEG := 1
HAVE_RBMP := 1
HAVE_RTGA := 1
HAVE_RGIF := 1
HAVE_7ZIP := 1
HAVE_NETWORKING := 1
HAVE_IFINFO := 1
@@ -971,7 +960,6 @@ else ifneq (,$(findstring unix,$(platform)))
HAVE_RJPEG := 1
HAVE_RBMP := 1
HAVE_RTGA := 1
HAVE_RGIF := 1
HAVE_7ZIP := 1
HAVE_NETWORKING := 1
HAVE_IFINFO := 1
@@ -1089,9 +1077,6 @@ endif
ifeq ($(HAVE_RTGA), 1)
CFLAGS += -DHAVE_RTGA
endif
ifeq ($(HAVE_RGIF), 1)
CFLAGS += -DHAVE_RGIF
endif
ifeq ($(HAVE_BSV_MOVIE), 1)
CFLAGS += -DHAVE_BSV_MOVIE
@@ -1144,12 +1129,6 @@ ifeq ($(HAVE_RFLV), 1)
CFLAGS += -DHAVE_RFLV
endif
ifeq ($(HAVE_MF_AUDIO), 1)
ifeq ($(system_platform), win)
CFLAGS += -DHAVE_MF_AUDIO
endif
endif
ifeq ($(HAVE_IFINFO), 1)
CFLAGS += -DHAVE_IFINFO
endif
-1
View File
@@ -29,7 +29,6 @@ HAVE_AUDIOMIXER = 1
HAVE_CC_RESAMPLER = 1
HAVE_MENU_COMMON = 1
HAVE_RTGA = 1
HAVE_RGIF = 1
HAVE_RPNG = 1
HAVE_RWEBP = 1
HAVE_RDDS = 1
-1
View File
@@ -54,7 +54,6 @@ HAVE_MENU_COMMON := 1
HAVE_RJPEG := 1
HAVE_RBMP := 1
HAVE_RTGA := 1
HAVE_RGIF := 1
HAVE_7ZIP := 1
HAVE_NETWORKING := 1
HAVE_IFINFO := 1
-1
View File
@@ -158,7 +158,6 @@ HAVE_RDDS := 0
HAVE_RJPEG := 1
HAVE_RBMP := 1
HAVE_RTGA := 1
HAVE_RGIF := 1
HAVE_RMODTRACKER := 0
HAVE_OVERLAY := 1
HAVE_7ZIP := 0
+1 -2
View File
@@ -34,7 +34,7 @@ ifeq ($(GRIFFIN_BUILD), 1)
OBJ += griffin/griffin.o
DEFINES += -DHAVE_GRIFFIN=1
DEFINES += -DHAVE_MENU -DHAVE_LIBRETRODB -DHAVE_CONFIGFILE
DEFINES += -DHAVE_RPNG -DHAVE_RWEBP -DHAVE_RDDS -DHAVE_RJPEG -DHAVE_RBMP -DHAVE_RTGA -DHAVE_RGIF -DHAVE_CC_RESAMPLER
DEFINES += -DHAVE_RPNG -DHAVE_RWEBP -DHAVE_RDDS -DHAVE_RJPEG -DHAVE_RBMP -DHAVE_RTGA -DHAVE_CC_RESAMPLER
DEFINES += -DHAVE_CORE_INFO_CACHE
ifeq ($(DEBUG), 1)
DEFINES += -DHAVE_NETLOGGER
@@ -50,7 +50,6 @@ else
HAVE_RJPEG := 1
HAVE_RBMP := 1
HAVE_RTGA := 1
HAVE_RGIF := 1
HAVE_OVERLAY := 1
HAVE_7ZIP := 1
HAVE_RZSTD := 1
-2
View File
@@ -37,7 +37,6 @@ ifeq ($(GRIFFIN_BUILD), 1)
-DHAVE_RJPEG \
-DHAVE_RBMP \
-DHAVE_RTGA \
-DHAVE_RGIF \
-DHAVE_CC_RESAMPLER \
-DHAVE_CORE_INFO_CACHE
ifeq ($(DEBUG), 1)
@@ -59,7 +58,6 @@ else
HAVE_RJPEG := 1
HAVE_RBMP := 1
HAVE_RTGA := 1
HAVE_RGIF := 1
HAVE_7ZIP := 1
HAVE_RZSTD := 1
ifeq ($(HAVE_VITAGLES), 1)
-1
View File
@@ -148,7 +148,6 @@ HAVE_RDDS := 1
HAVE_RJPEG := 1
HAVE_RBMP := 1
HAVE_RTGA := 1
HAVE_RGIF := 1
HAVE_RMODTRACKER := 1
HAVE_OVERLAY := 1
HAVE_7ZIP := 1
+1 -2
View File
@@ -122,7 +122,7 @@ endif
DEFINES += -DHAVE_RWAV
DEFINES += -DHAVE_GRIFFIN=1 -DHAVE_MENU -DHAVE_GFX_WIDGETS -DHAVE_CONFIGFILE -DHAVE_PATCH -DHAVE_CHEATS -DHAVE_RGUI -DHAVE_LIBRETRODB
DEFINES += -DHAVE_REWIND
DEFINES += -DHAVE_RPNG -DHAVE_RWEBP -DHAVE_RDDS -DHAVE_RJPEG -DHAVE_RBMP -DHAVE_RTGA -DHAVE_RGIF -DHAVE_CC_RESAMPLER
DEFINES += -DHAVE_RPNG -DHAVE_RWEBP -DHAVE_RDDS -DHAVE_RJPEG -DHAVE_RBMP -DHAVE_RTGA -DHAVE_CC_RESAMPLER
DEFINES += -DHAVE_RSLC -DHAVE_SLANG
DEFINES += -DHAVE_RVORBIS -DHAVE_LANGEXTRA -DHAVE_LIBRETRODB -DHAVE_NETWORKING -DHAVE_IFINFO -DHAVE_NETPLAYDISCOVERY
DEFINES += -DHAVE_XMB -DHAVE_MATERIALUI
@@ -139,7 +139,6 @@ endif
HAVE_MENU_COMMON = 1
HAVE_GFX_WIDGETS = 1
HAVE_RTGA = 1
HAVE_RGIF = 1
HAVE_RPNG = 1
HAVE_RWEBP = 1
HAVE_RDDS = 1
+1 -4
View File
@@ -1443,10 +1443,7 @@ static int rcheevos_rvz_pump(rcheevos_rvz_t* handle, bool opening)
if (err != RVZ_PENDING)
return err;
/* At the offset in one call; seek and read where there is none */
if ((got = filestream_read_at(handle->file, req.dst,
(int64_t)req.length, (int64_t)req.offset)) < 0
&& filestream_seek(handle->file, (int64_t)req.offset,
if (filestream_seek(handle->file, (int64_t)req.offset,
RETRO_VFS_SEEK_POSITION_START) == 0)
got = filestream_read(handle->file, req.dst, (int64_t)req.length);
rvz_feed(handle->rvz, got > 0 ? (size_t)got : 0);
+217 -77
View File
@@ -3194,15 +3194,22 @@ static uint8_t *command_memory_get_pointer(
/* What RUN_UNTIL, a PRESS that waits after it and a STEPS list wait on:
* the byte at @lo, or with @wide the value @hi * 256 + @lo, from two
* bytes that need not be adjacent. */
* bytes that need not be adjacent. With @diff, that less the value at
* @sub_lo, or @sub_hi:@sub_lo: how far apart two things are, signed. */
struct command_cond
{
unsigned hi;
unsigned lo;
unsigned sub_hi;
unsigned sub_lo;
unsigned mask; /* "& <mask>": the bits compared; 0 for all */
unsigned want;
int want;
uint8_t op; /* enum cmd_until_op */
bool wide;
bool sub_wide;
bool diff;
/* a stop: fires only on a frame it holds after one it did not */
bool edge;
};
/* "<address>[:<address>]" into @c, @end after it: 0, or 1 where the
@@ -3225,20 +3232,34 @@ static int command_cond_address(const char *s, struct command_cond *c,
return 0;
}
static bool command_cond_read(const struct command_cond *c,
/* The byte at @lo, or with @wide the value @hi * 256 + @lo. */
static bool command_cond_value(unsigned hi, unsigned lo, bool wide,
unsigned *out, char *why, size_t why_len)
{
unsigned avail = 0;
const rarch_system_info_t *sys = &runloop_state_get_ptr()->system;
const uint8_t *lo = command_memory_get_pointer(sys, c->lo, &avail, 0,
const uint8_t *l = command_memory_get_pointer(sys, lo, &avail, 0,
why, why_len);
const uint8_t *hi = NULL;
if (!lo || (c->wide && !(hi = command_memory_get_pointer(sys, c->hi,
const uint8_t *h = NULL;
if (!l || (wide && !(h = command_memory_get_pointer(sys, hi,
&avail, 0, why, why_len))))
return false;
*out = hi ? ((unsigned)*hi << 8) | *lo : *lo;
*out = h ? ((unsigned)*h << 8) | *l : *l;
return true;
}
static bool command_cond_read(const struct command_cond *c,
int *out, char *why, size_t why_len)
{
unsigned a = 0;
unsigned b = 0;
if ( !command_cond_value(c->hi, c->lo, c->wide, &a, why, why_len)
|| (c->diff && !command_cond_value(c->sub_hi, c->sub_lo,
c->sub_wide, &b, why, why_len)))
return false;
if (c->mask)
*out &= c->mask;
a &= c->mask;
*out = (int)a - (int)b;
return true;
}
@@ -3291,9 +3312,9 @@ static size_t command_watch_lines(char *s, size_t len)
i++)
{
const struct command_watch_entry *e = &command_watches[i];
unsigned now = 0;
int now = 0;
if (command_cond_read(&e->where, &now, reason, sizeof(reason)))
snprintf(value, sizeof(value), "%u", now);
snprintf(value, sizeof(value), "%d", now);
else
strlcpy(value, "none", sizeof(value));
if (e->where.wide)
@@ -3338,15 +3359,17 @@ static bool command_cond_number(const char *s, char **end,
return errno != ERANGE;
}
/* "<address>[:<address>] <condition> <value>", @end after the value;
* false with what was wrong in @why. */
/* "<address>[:<address>] [- <address>[:<address>]] <condition>
* <value>", @end after the value; false with what was wrong in @why. */
static bool command_cond_parse(const char *s, struct command_cond *c,
char **end, char *why, size_t why_len)
{
unsigned i;
unsigned long num;
unsigned long max;
const char *sp;
int bad;
bool neg = false;
memset(c, 0, sizeof(*c));
if ((bad = command_cond_address(s, c, end)))
@@ -3359,6 +3382,32 @@ static bool command_cond_parse(const char *s, struct command_cond *c,
}
while (**end == ' ')
(*end)++;
/* "485 - 47e": the second's value taken from the first's, signed,
* so how far an enemy is from the player is one condition */
if (**end == '-')
{
struct command_cond sub;
memset(&sub, 0, sizeof(sub));
if (command_cond_address(*end + 1, &sub, end))
{
strlcpy(why, "a hexadecimal address, or two as high:low, after "
"the \"-\"", why_len);
return false;
}
c->sub_hi = sub.hi;
c->sub_lo = sub.lo;
c->sub_wide = sub.wide;
c->diff = true;
while (**end == ' ')
(*end)++;
}
max = (c->wide || c->sub_wide) ? 65535UL : 255UL;
if (**end == '&' && c->diff)
{
strlcpy(why, "a mask compares one address's bits, not a difference",
why_len);
return false;
}
/* "& 0x40" or "& 64": only those bits, as a game keeps its flags */
if (**end == '&')
{
@@ -3397,17 +3446,29 @@ static bool command_cond_parse(const char *s, struct command_cond *c,
}
while (*sp == ' ')
sp++;
/* "== 112" or "== 0x70", as a mask is given */
if ( !command_cond_number(sp, end, &num)
|| num > (c->wide ? 65535UL : 255UL))
/* a difference may be below zero: "<= -16" */
if (c->diff && *sp == '-')
{
strlcpy(why, c->wide
? "a value from 0 to 65535 (0xFFFF), which is what two bytes hold"
: "a value from 0 to 255 (0xFF), which is what a byte holds",
why_len);
neg = true;
sp++;
}
/* "== 112" or "== 0x70", as a mask is given */
if (!command_cond_number(sp, end, &num) || num > max)
{
if (c->diff)
strlcpy(why, max > 255UL
? "a value from -65535 to 65535, which is what two values "
"of two bytes differ by"
: "a value from -255 to 255, which is what two bytes "
"differ by", why_len);
else
strlcpy(why, c->wide
? "a value from 0 to 65535 (0xFFFF), which is what two bytes hold"
: "a value from 0 to 255 (0xFF), which is what a byte holds",
why_len);
return false;
}
c->want = (unsigned)num;
c->want = neg ? -(int)num : (int)num;
c->op = (uint8_t)i;
return true;
}
@@ -3415,7 +3476,7 @@ static bool command_cond_parse(const char *s, struct command_cond *c,
/* What @c's memory holds now, looked up afresh as WATCH's bytes are,
* since a core may move its memory while the content runs; false where
* nothing maps it, with the reason as line clients read it in @why. */
static bool command_cond_met(const struct command_cond *c, unsigned now)
static bool command_cond_met(const struct command_cond *c, int now)
{
switch (c->op)
{
@@ -3437,7 +3498,7 @@ static bool command_cond_mapped(command_t *cmd, const char *name,
const struct command_cond *c)
{
char reason[128];
unsigned now = 0;
int now = 0;
if (command_cond_read(c, &now, reason, sizeof(reason)))
return true;
command_reply_error(cmd, name, "%s", command_memory_why(reason));
@@ -3505,12 +3566,15 @@ static struct
unsigned left; /* frames left in a RUN or PRESS step */
unsigned budget; /* frames left for the whole job */
unsigned ran; /* frames run so far */
unsigned value; /* what the last condition read held */
int value; /* what the last condition read held */
unsigned port; /* the player whose buttons are held */
uint16_t held; /* the buttons the job let go of, by bit */
uint8_t answer; /* enum cmd_job_answer */
unsigned nstops;
unsigned stopped; /* which stop held, from 1 */
/* whether each stop held on the frame before: one that becomes
* fires only where it did not */
bool stop_was[COMMAND_STOPS_MAX];
/* a frame with the buttons let go between two presses of the same
* one, so the game sees two taps rather than one long press */
bool gap;
@@ -3632,7 +3696,7 @@ static void command_run_frames_end(const char *how)
case CMD_ANSWER_UNTIL:
snprintf(first, sizeof(first), "%s %u\n", how,
command_run_frames_st.ran);
snprintf(last, sizeof(last), "VALUE %u\n",
snprintf(last, sizeof(last), "VALUE %d\n",
command_run_frames_st.value);
command_run_frames_answer(first, last, false);
break;
@@ -3777,8 +3841,14 @@ static void command_run_frames_enter(bool safe)
}
else
{
int now = 0;
command_run_frames_st.stops[s->idx - 1] = s->cond;
command_run_frames_st.nstops = s->idx;
/* what it holds as it takes over, so one already true when
* the list starts waits for it to stop holding first */
command_run_frames_st.stop_was[s->idx - 1] =
command_cond_read(&s->cond, &now, why, sizeof(why))
&& command_cond_met(&s->cond, now);
}
command_run_frames_st.cur++;
continue;
@@ -3927,7 +3997,7 @@ void command_run_frames_between(void)
void command_run_frames_tick(void)
{
char why[128];
unsigned now = 0;
int now = 0;
unsigned i;
struct command_step *s;
@@ -3948,10 +4018,17 @@ void command_run_frames_tick(void)
}
if (command_cond_met(&command_run_frames_st.stops[i], now))
{
command_run_frames_st.stopped = i + 1;
command_run_frames_end("STOPPED");
return;
bool was = command_run_frames_st.stop_was[i];
command_run_frames_st.stop_was[i] = true;
if (!command_run_frames_st.stops[i].edge || !was)
{
command_run_frames_st.stopped = i + 1;
command_run_frames_end("STOPPED");
return;
}
}
else
command_run_frames_st.stop_was[i] = false;
}
s = &command_run_frames_st.steps[command_run_frames_st.cur];
if (command_run_frames_st.gap)
@@ -4284,12 +4361,14 @@ bool command_set_input(command_t *cmd, const char *arg)
* With nothing, what is watched now. Each label and address watches the
* byte there under that label, carried by RUN_FRAMES, PRESS and
* RUN_UNTIL; a label and "off" stops watching it. Every pair is taken
* or none is, so a refusal leaves the list as it was.
* or none is, so a refusal leaves the list as it was. The limit is on
* the list they leave, so an off later in the request makes room.
*
* Answers with the list either way, so a client sees what it has. */
bool command_watch(command_t *cmd, const char *arg)
{
struct command_watch_entry next[COMMAND_WATCH_MAX];
/* room past the limit for those an off further on takes back out */
struct command_watch_entry next[2 * COMMAND_WATCH_MAX];
char reply[64 + COMMAND_WATCH_MAX * COMMAND_WATCH_LINE];
char label[sizeof(next[0].label)];
char reason[128];
@@ -4299,7 +4378,7 @@ bool command_watch(command_t *cmd, const char *arg)
unsigned i;
const char *sp;
memcpy(next, command_watches, sizeof(next));
memcpy(next, command_watches, sizeof(command_watches));
while (arg && *arg)
{
while (*arg == ' ')
@@ -4346,7 +4425,7 @@ bool command_watch(command_t *cmd, const char *arg)
else
{
struct command_cond where;
unsigned now = 0;
int now = 0;
char *end = NULL;
memset(&where, 0, sizeof(where));
/* high:low, two bytes as one value, as conditions take them */
@@ -4358,7 +4437,7 @@ bool command_watch(command_t *cmd, const char *arg)
return false;
}
/* only a label that is not watched yet needs room */
if (i == count && count >= COMMAND_WATCH_MAX)
if (i == count && count >= ARRAY_SIZE(next))
{
command_reply_error(cmd, "WATCH", "at most %u bytes watched "
"at once", (unsigned)COMMAND_WATCH_MAX);
@@ -4378,7 +4457,13 @@ bool command_watch(command_t *cmd, const char *arg)
strlcpy(next[i].label, label, sizeof(next[i].label));
}
}
memcpy(command_watches, next, sizeof(next));
if (count > COMMAND_WATCH_MAX)
{
command_reply_error(cmd, "WATCH", "at most %u bytes watched "
"at once", (unsigned)COMMAND_WATCH_MAX);
return false;
}
memcpy(command_watches, next, sizeof(command_watches));
command_watch_count = count;
_len = command_watch_lines(reply, sizeof(reply));
@@ -4388,11 +4473,12 @@ bool command_watch(command_t *cmd, const char *arg)
return true;
}
/* RUN_UNTIL <address> <condition> <value> [max frames]
/* RUN_UNTIL <address> [- <address>] <condition> <value> [max frames]
*
* Runs the content until the byte at a system address meets what was
* asked, then answers with how many frames that took and the value it
* found. Where a client would otherwise run a few frames, read the
* found. With "- <address>" it is that byte less the other, signed:
* how far apart two things are. Where a client would otherwise run a few frames, read the
* byte, and go round again - which is where a field run spent most of
* its calls - this is one request.
*
@@ -4604,7 +4690,9 @@ static void command_steps_report(command_t *cmd, long idle,
* <player> <controls> <frames>" and "until <condition>", in order, then
* answers with how it ended and what WATCH watches. A "stop
* <condition>" entry ends the list after any frame where it holds, so a
* death does not play out the rest, and "checkpoint" keeps the state
* death does not play out the rest; "stop becomes <condition>" only
* after one where it starts to, so one already true does not end the
* list at its first frame. "checkpoint" keeps the state
* STATE rollback returns to. The whole list runs no longer than a wait
* does; past that it answers WAITING and the step it was on, and the
* next request carries on from there.
@@ -4662,9 +4750,10 @@ bool command_steps(command_t *cmd, const char *arg)
for (entry = list; entry; entry = next)
{
struct command_step *s;
struct command_cond *c = NULL;
char *end = NULL;
struct command_cond *c = NULL;
char *end = NULL;
size_t n;
bool edge = false;
if ((next = strchr(entry, ';')))
*next++ = '\0';
while (*entry == ' ')
@@ -4686,6 +4775,13 @@ bool command_steps(command_t *cmd, const char *arg)
}
c = &stops[nstops++];
entry += 5;
/* "stop becomes <condition>": only once it starts to hold, so
* one true as the list starts does not end it at once */
if (!strncmp(entry, "becomes ", 8))
{
entry += 8;
edge = true;
}
}
else if (count >= COMMAND_STEPS_MAX)
{
@@ -4785,6 +4881,7 @@ bool command_steps(command_t *cmd, const char *arg)
command_reply_error(cmd, "STEPS", "%s", why);
return false;
}
c->edge = edge;
while (*end == ' ')
end++;
if (*end)
@@ -6091,11 +6188,23 @@ bool command_get_status(command_t *cmd, const char* arg)
return true;
}
/* READ_CORE_MEMORY <address> <bytes> [<address> <bytes>]...
*
* Each range a line of its own, in the order asked, so the arrays a
* step needs - positions, health - are one request rather than one
* apiece. Where nothing maps one, that line alone is the answer. */
#define COMMAND_READ_RANGES_MAX 16
bool command_read_memory(command_t *cmd, const char *arg)
{
char* reply = NULL;
char* reply_at = NULL;
const uint8_t* data = NULL;
unsigned int addrs[COMMAND_READ_RANGES_MAX];
unsigned int counts[COMMAND_READ_RANGES_MAX];
unsigned int nranges = 0;
unsigned int total = 0;
unsigned int r;
unsigned int nbytes = 0;
unsigned int alloc_size = 0;
unsigned int address = -1;
@@ -6104,27 +6213,48 @@ bool command_read_memory(command_t *cmd, const char *arg)
runloop_state_t *runloop_st = runloop_state_get_ptr();
const rarch_system_info_t* sys_info= &runloop_st->system;
while (arg && *arg)
{
char *end = NULL;
unsigned long num;
if (nranges >= COMMAND_READ_RANGES_MAX)
{
command_reply_error(cmd, "READ_CORE_MEMORY",
"at most %u ranges", (unsigned)COMMAND_READ_RANGES_MAX);
return false;
}
if (!command_parse_address(arg, &address, &end) || *end != ' ')
{
command_reply_error(cmd, "READ_CORE_MEMORY",
"a hexadecimal address, a space and a byte count");
return false;
}
num = strtoul(end + 1, NULL, 10);
num = strtoul(end + 1, &end, 10);
nbytes = num <= COMMAND_READ_NBYTES_MAX ? (unsigned)num : 0;
if (nbytes == 0)
if (nbytes == 0 || total + nbytes > COMMAND_READ_NBYTES_MAX)
{
command_reply_error(cmd, "READ_CORE_MEMORY",
"a byte count from 1 to %u", COMMAND_READ_NBYTES_MAX);
command_reply_error(cmd, "READ_CORE_MEMORY", nranges
? "byte counts from 1, %u in all"
: "a byte count from 1 to %u", COMMAND_READ_NBYTES_MAX);
return false;
}
addrs[nranges] = address;
counts[nranges] = nbytes;
nranges++;
total += nbytes;
/* another address and count, or the end of the line */
for (arg = end; *arg && (unsigned char)*arg <= ' '; arg++)
;
}
if (!nranges)
{
command_reply_error(cmd, "READ_CORE_MEMORY",
"a hexadecimal address, a space and a byte count");
return false;
}
/* Ensure large enough to return all requested bytes or an error message */
alloc_size = 96 + nbytes * 3;
alloc_size = 96 * nranges + total * 3;
reply = (char*)malloc(alloc_size);
if (!reply)
@@ -6132,43 +6262,53 @@ bool command_read_memory(command_t *cmd, const char *arg)
command_reply_error(cmd, "READ_CORE_MEMORY", "out of memory");
return false;
}
reply_at = reply + snprintf(reply, alloc_size - 1, "READ_CORE_MEMORY %x", address);
if ((data = command_memory_get_pointer(
sys_info, address, &max_bytes,
0, reply_at, alloc_size - strlen(reply))))
for (r = 0; r < nranges; r++)
{
char why[128];
char *end = reply_at;
unsigned int read = 0;
/* on into the region that follows, as a core that splits its RAM
* maps it; where nothing maps the rest, how much was read */
while (data)
char *line = reply + _len;
address = addrs[r];
nbytes = counts[r];
reply_at = line + snprintf(line, alloc_size - _len - 1,
"READ_CORE_MEMORY %x", address);
if ((data = command_memory_get_pointer(
sys_info, address, &max_bytes,
0, reply_at, alloc_size - (size_t)(reply_at - reply))))
{
unsigned int n = nbytes - read < max_bytes
? nbytes - read : max_bytes;
if (!n)
break;
end = command_hex_bytes(end, data, n);
read += n;
if (read >= nbytes)
break;
data = command_memory_get_pointer(sys_info, address + read,
&max_bytes, 0, why, sizeof(why));
char why[128];
char *end = reply_at;
unsigned int read = 0;
/* on into the region that follows, as a core that splits its RAM
* maps it; where nothing maps the rest, how much was read */
while (data)
{
unsigned int n = nbytes - read < max_bytes
? nbytes - read : max_bytes;
if (!n)
break;
end = command_hex_bytes(end, data, n);
read += n;
if (read >= nbytes)
break;
data = command_memory_get_pointer(sys_info, address + read,
&max_bytes, 0, why, sizeof(why));
}
*end++ = '\n';
if (read < nbytes)
end += snprintf(end, alloc_size - (size_t)(end - reply),
"TRUNCATED %u\n", read);
_len = (size_t)(end - reply);
}
else
{
/* command_memory_get_pointer() has put the reason in the reply,
* in the form line clients have always read: this range's line
* alone */
_len = strlen(line);
memmove(reply, line, _len + 1);
cmd->error = true;
break;
}
*end++ = '\n';
if (read < nbytes)
end += snprintf(end, alloc_size - (size_t)(end - reply),
"TRUNCATED %u\n", read);
_len = (size_t)(end - reply);
}
else
{
/* command_memory_get_pointer() has put the reason in the reply,
* in the form line clients have always read */
_len = strlen(reply);
cmd->error = true;
}
cmd->replier(cmd, reply, _len);
+25 -8
View File
@@ -603,6 +603,11 @@ struct cmd_rows
/* The reply may carry a "PREVIOUS ..." line: how a queued STEPS no
* reply has told of ended. */
bool previous;
/* Set, for a record: the field a reply of several such lines - one
* for each range READ_CORE_MEMORY was asked - gives them all in, in
* order, each with the trailers after it. The record's own fields
* are the first. */
const char *more;
};
/* A command with its own handler; @arg_desc names the argument, or
@@ -876,18 +881,19 @@ static const struct cmd_param cmd_params_watch[] = {
{ "watches", "Label and hexadecimal address pairs, as GET_MEMORY_MAP "
"gives them: \"x 86 mode 770\"; \"x 6d:86\" reads two bytes as one "
"value. A label watched again is replaced; off as its address stops "
"it. 16 at most.",
"it. 16 at most, counted once the offs are taken.",
CMD_PARAM_STRING, false, NULL, NULL, NULL },
{ NULL }
};
static const struct cmd_param cmd_params_until[] = {
{ "address", "Hexadecimal, as GET_MEMORY_MAP gives it; high:low "
"(6d:86) reads two bytes as one value; & 0x40 after it compares "
"only those bits.", CMD_PARAM_STRING, true, NULL, NULL, NULL },
"only those bits; 485 - 47e compares the first less the second, "
"signed.", CMD_PARAM_STRING, true, NULL, NULL, NULL },
{ "condition", "How it compares with the value.",
CMD_PARAM_STRING, true, NULL, "==|!=|<|>|<=|>=", NULL },
{ "value", "0 to 255, or 65535 for high:low.",
CMD_PARAM_INT, true, NULL, NULL, NULL },
{ "value", "0 to 255, or 65535 for high:low; a difference from "
"-255, or -65535.", CMD_PARAM_INT, true, NULL, NULL, NULL },
{ "frames", "Frames to wait at most; a request's nine seconds when "
"left out.", CMD_PARAM_INT, false, NULL, NULL, NULL },
{ NULL }
@@ -910,7 +916,8 @@ static const struct cmd_param cmd_params_steps[] = {
"<frames>, until <condition> as RUN_UNTIL's, checkpoint, and up to "
"four stop <condition> that end it: \"until 86 >= 200; "
"press 1 a 20; until 1d == 0; stop e == 11\". 32 at most. A press "
"after a press lets go for a frame first.",
"after a press lets go for a frame first. stop becomes <condition> "
"ends it only once it starts to hold, not where it already does.",
CMD_PARAM_STRING, true, NULL, NULL, NULL },
{ "queue", "on: answer now, run after those queued, pause when all "
"have (idle: ms since). After a queued list ends the next reply says "
@@ -972,6 +979,16 @@ static const struct cmd_param cmd_params_read[] = {
CMD_PARAM_INT, true, NULL, NULL, NULL },
{ NULL }
};
static const struct cmd_param cmd_params_read_memory[] = {
{ "address", "The address to read from, in hexadecimal.",
CMD_PARAM_STRING, true, NULL, NULL, NULL },
{ "bytes", "How many.",
CMD_PARAM_INT, true, NULL, NULL, NULL },
{ "more", "Further ranges in the same request, as address and byte "
"count pairs: \"4a2 18 568 18\". Each answers a line, given as "
"ranges.", CMD_PARAM_STRING, false, NULL, NULL, NULL },
{ NULL }
};
static const struct cmd_param cmd_params_write[] = {
{ "address", "The address to write to, in hexadecimal.",
CMD_PARAM_STRING, true, NULL, NULL, NULL },
@@ -1212,7 +1229,7 @@ static const struct cmd_trailer cmd_trailers_read[] = {
{ "TRUNCATED", "truncated", "read", "Bytes read, short of those asked." },
{ NULL }
};
static const struct cmd_rows cmd_rows_read = { cmd_cols_read, cmd_trailers_read, 0, 0, " " };
static const struct cmd_rows cmd_rows_read = { cmd_cols_read, cmd_trailers_read, 0, 0, " ", false, "ranges" };
/* "MENU Main Menu", the entries, then which is selected of how many */
static const struct cmd_column cmd_cols_menu[] = {
{ "index", NULL },
@@ -1258,7 +1275,7 @@ static const struct cmd_action_map action_map[] = {
{ "RUN_FRAMES", command_run_frames, "<count>", "Pause and advance the content some frames; it finishes paused. One request runs nine seconds of frames at most (540 at 60fps), as PRESS, RUN_UNTIL and STEPS do.", 0, cmd_params_run_frames, &cmd_rows_frames },
{ "SET_INPUT", command_set_input, "<player> <control>[+<control>...] <value>", "Hold RetroPad buttons or stick axes for the core, over the player's own input, until set again or released. The core is given exactly what is held: opposing directions are not cleaned and the D-Pad is not turned with the picture. Under netplay the player is this machine's, and what is held is sent like a press. Answers with the player, the buttons held and the axes held, none for either where nothing is.", CMD_INFO_NO_TOOL, cmd_params_input, &cmd_rows_input },
{ "PRESS", command_press, "<player> <control>[+<control>...] <frames> [until <condition>]", "Press buttons for some frames and let go; with until, run on until a condition holds. What INPUT holds stays held. Answers with what WATCH watches; finishes paused.", 0, cmd_params_press, &cmd_rows_press },
{ "RUN_UNTIL", command_run_until, "<address>[:<address>] <condition> <value> [max frames]", "Run until memory meets a condition. Answers met or waiting (ask again) with the frames run, what WATCH watches and the value.", 0, cmd_params_until, &cmd_rows_until },
{ "RUN_UNTIL", command_run_until, "<address>[:<address>] [- <address>[:<address>]] <condition> <value> [max frames]", "Run until memory meets a condition. Answers met or waiting (ask again) with the frames run, what WATCH watches and the value.", 0, cmd_params_until, &cmd_rows_until },
{ "STEPS", command_steps, "<step>[; <step>...][|on]", "Play a stretch in one request, or queued to play on unpaused. Answers with how it ended and what WATCH watches.", 0, cmd_params_steps, &cmd_rows_steps },
{ "WATCH", command_watch, "[<label> <address|off>]...", "Watch bytes under labels: every step answers with them, so needs no read after. With none, answers each value, in decimal. Cleared when content closes.", 0, cmd_params_watch, &cmd_rows_watch },
{ "RELEASE_INPUT", command_release_input, "[player]", "Let go of everything SET_INPUT holds, for one player, or every player when given none. Answers as GET_INPUT does, for that player or the first.", CMD_INFO_NO_TOOL, cmd_params_input_release, &cmd_rows_input },
@@ -1275,7 +1292,7 @@ static const struct cmd_action_map action_map[] = {
{ "READ_CORE_RAM", command_read_ram, "<address> <number of bytes>", "Read bytes from core memory at an achievement address (needs a game with achievements).", CMD_INFO_READ_ONLY | CMD_INFO_NO_TOOL, cmd_params_read },
{ "WRITE_CORE_RAM", command_write_ram, "<address> <byte1> <byte2> ...", "Write bytes to core memory at an achievement address (needs a game with achievements).", CMD_INFO_DESTRUCTIVE | CMD_INFO_NO_TOOL, cmd_params_write },
#endif
{ "READ_CORE_MEMORY", command_read_memory, "<address> <number of bytes>", "Read bytes from core memory at a system address. Answers with the address and the bytes, in hexadecimal.", CMD_INFO_READ_ONLY, cmd_params_read, &cmd_rows_read },
{ "READ_CORE_MEMORY", command_read_memory, "<address> <number of bytes> [<address> <number of bytes>]...", "Read bytes from core memory at a system address. Answers with the address and the bytes, in hexadecimal; a line for each range asked.", CMD_INFO_READ_ONLY, cmd_params_read_memory, &cmd_rows_read },
{ "GET_MEMORY_MAP", command_get_memory_map, "No argument", "The core's memory map: start, length, select and disconnect in hexadecimal, as READ_CORE_MEMORY takes them. A core with none lists the RAM it hands over, in space core: system RAM from 0, save RAM after.", CMD_INFO_READ_ONLY, NULL, &cmd_rows_memory },
{ "WRITE_CORE_MEMORY",command_write_memory, "<address> <byte1> <byte2> ...", "Write bytes to core memory at a system address. Answers with the address and how many bytes were written.", CMD_INFO_DESTRUCTIVE, cmd_params_write },
-1
View File
@@ -894,7 +894,6 @@
#define DEFAULT_SETTINGS_SHOW_ACCESSIBILITY true
#define DEFAULT_SETTINGS_SHOW_POWER_MANAGEMENT true
#define DEFAULT_SETTINGS_SHOW_ACHIEVEMENTS true
#define DEFAULT_SETTINGS_SHOW_BLUETOOTH true
#define DEFAULT_SETTINGS_SHOW_NETWORK true
#define DEFAULT_SETTINGS_SHOW_PLAYLISTS true
#define DEFAULT_SETTINGS_SHOW_USER true
-6
View File
@@ -418,12 +418,6 @@
#define SUPPORTS_RTGA false
#endif
#ifdef HAVE_RGIF
#define SUPPORTS_RGIF true
#else
#define SUPPORTS_RGIF false
#endif
#ifdef HAVE_RWEBP
#define SUPPORTS_RWEBP true
#else
-1
View File
@@ -1015,7 +1015,6 @@ typedef struct settings
bool settings_show_accessibility;
bool settings_show_power_management;
bool settings_show_achievements;
bool settings_show_bluetooth;
bool settings_show_network;
bool settings_show_playlists;
bool settings_show_user;
+2 -6
View File
@@ -12,7 +12,7 @@
#include <streams/file_stream.h>
#if defined(HAVE_RPNG) || defined(HAVE_RJPEG) || defined(HAVE_RTGA) || defined(HAVE_RBMP) || defined(HAVE_RWEBP) || defined(HAVE_RDDS) || defined(HAVE_RGIF)
#if defined(HAVE_RPNG) || defined(HAVE_RJPEG) || defined(HAVE_RTGA) || defined(HAVE_RBMP) || defined(HAVE_RWEBP) || defined(HAVE_RDDS)
#define PREFER_NON_STB_IMAGE
#endif
@@ -87,10 +87,6 @@ static const char image_formats[] =
"|tga"
#endif
#ifdef HAVE_RGIF
"|gif"
#endif
#ifdef HAVE_RWEBP
"|webp"
#endif
@@ -99,7 +95,7 @@ static const char image_formats[] =
"|dds"
#endif
#if !defined(HAVE_RJPEG) && !defined(HAVE_RPNG) && !defined(HAVE_RBMP) && !defined(HAVE_RTGA) && !defined(HAVE_RWEBP) && !defined(HAVE_RDDS) && !defined(HAVE_RGIF)
#if !defined(HAVE_RJPEG) && !defined(HAVE_RPNG) && !defined(HAVE_RBMP) && !defined(HAVE_RTGA) && !defined(HAVE_RWEBP) && !defined(HAVE_RDDS)
#error "can't build this core with no image formats"
#endif
;
+25 -2
View File
@@ -143,6 +143,15 @@ goes on into the next; where nothing maps the rest it stops there and
says so, `TRUNCATED 2` after the bytes, given as `truncated: true,
read: 2`.
`READ_CORE_MEMORY 47e 18 4a2 18 568 18` reads several ranges in one
request (`more: "4a2 18 568 18"` over MCP), up to sixteen and 16384
bytes in all: a line for each, in the order asked, each with its own
`TRUNCATED` after it where it was cut short. The record's fields are
the first range's, and `ranges` gives every one, the first too, as
`{"address", "bytes"}` with `truncated` and `read` where cut short.
Where nothing maps one of them, its line alone is the answer, as a
single range's is.
## Results that are rows
The replies that are lines of tab-separated fields - `OPTION`,
@@ -446,7 +455,9 @@ its place in the list when its address changes; with nothing watched
it answers `WATCH none`. Values are decimal, 0 to 255 - or to 65535
for a `high:low` watch - as `RUN_UNTIL` takes them; addresses are hexadecimal. A label is up to 15 characters,
with no tab or newline in it. `x 6d:86` watches two bytes as one value,
high:low, as conditions read them. Sixteen at once. Each is checked when it is
high:low, as conditions read them. Sixteen at once, counted on the
list the request leaves: `WATCH lives 4d e13h off` with sixteen watched
adds one and drops one. Each is checked when it is
set - an address nothing maps is refused there -
and read afresh on every reply, so a core that moves its memory is
followed; one that stops mapping a watched address answers `none` for
@@ -473,6 +484,14 @@ x 7e0086 52
VALUE 5
```
`<address> - <address>` compares the first's value less the second's,
signed, each one byte or `high:low`: `485 - 47e <= 32` waits until an
enemy at x `485` is no more than 32 to the right of the player at
`47e`, walking in until it is in range. The value may be below zero, from -255 to 255, or -65535 to
65535 where either side is `high:low`, and `VALUE` answers the
difference, `VALUE -12`. Both addresses must be mapped, and a mask is
refused on one.
Where a client would otherwise run a few frames, read the byte and go
round again, this is one request. The address is the kind
`GET_MEMORY_MAP` gives and `READ_CORE_MEMORY` takes, and one nothing
@@ -493,7 +512,11 @@ told it failed.
step is `run <frames>`, `press <player> <controls> <frames>`, `until
<condition>` or `checkpoint`, in order; up to four `stop <condition>`
entries anywhere in the list end it after any frame where one holds - a
death, the level's end - so neither plays out the rest. `checkpoint`
death, the level's end - so neither plays out the rest. `stop becomes
<condition>` ends it only after a frame where the condition starts to
hold: one already true when the list starts - `stop becomes 412 == 4`
while the player is still reeling - waits for it to stop holding and
hold again, rather than ending the list at its first frame. `checkpoint`
keeps the state `STATE rollback` returns to, where the list has got to,
so a stretch can mark its own retry point:
+45 -7
View File
@@ -3010,7 +3010,45 @@ void dxgi_set_hdr_metadata(
#include <math.h>
#include <stdint.h>
#include <formats/rpng.h>
#include <math/float16.h>
/* IEEE 754 binary16 -> binary32. Used to decode FP16 scRGB samples. */
static INLINE float dxgi_half_to_float(uint16_t h)
{
uint32_t sign = (uint32_t)(h >> 15) & 0x1u;
uint32_t exp = (uint32_t)(h >> 10) & 0x1Fu;
uint32_t mant = (uint32_t) h & 0x3FFu;
uint32_t f;
union { uint32_t u; float f; } u;
if (exp == 0)
{
if (mant == 0)
f = sign << 31; /* signed zero */
else
{
/* Subnormal: normalize. */
while (!(mant & 0x400u))
{
mant <<= 1;
exp -= 1; /* exp starts at 0, goes negative */
}
exp += 1;
mant &= ~0x400u;
f = (sign << 31) | ((exp + 127 - 15) << 23) | (mant << 13);
}
}
else if (exp == 0x1F)
{
/* Inf / NaN: propagate to float32 Inf/NaN with the same mantissa
* low bits (clamped away later, so exact bit-pattern doesn't matter). */
f = (sign << 31) | (0xFFu << 23) | (mant << 13);
}
else
f = (sign << 31) | ((exp + 127 - 15) << 23) | (mant << 13);
u.u = f;
return u.f;
}
/* ST.2084 (PQ) EOTF. Input is the non-linear PQ code value in [0,1];
* output is linear light normalized so 1.0 == 10000 nits. */
@@ -3172,9 +3210,9 @@ bool dxgi_hdr_readback_to_bgr24(
const uint16_t* src = (const uint16_t*)src_row + src_x * 4;
for (x = 0; x < width; x++)
{
float r = retro_half_to_float(src[4 * x + 0]) * inv_scale;
float g = retro_half_to_float(src[4 * x + 1]) * inv_scale;
float b = retro_half_to_float(src[4 * x + 2]) * inv_scale;
float r = dxgi_half_to_float(src[4 * x + 0]) * inv_scale;
float g = dxgi_half_to_float(src[4 * x + 1]) * inv_scale;
float b = dxgi_half_to_float(src[4 * x + 2]) * inv_scale;
/* scRGB carries legal negative values for out-of-gamut
* colours; clamping in LinearToSRGB handles them. */
dst[3 * x + 0] = dxgi_float_to_unorm8(dxgi_linear_to_srgb(b));
@@ -3271,9 +3309,9 @@ bool dxgi_hdr_readback_to_rgb16(
* scale to absolute nits, PQ-encode into 16 bit. Extended
* range (negatives, >10000 nits) clamps -- unavoidable for
* a UNORM PNG. */
float r = retro_half_to_float(src[x * 4 + 0]);
float g = retro_half_to_float(src[x * 4 + 1]);
float b = retro_half_to_float(src[x * 4 + 2]);
float r = dxgi_half_to_float(src[x * 4 + 0]);
float g = dxgi_half_to_float(src[x * 4 + 1]);
float b = dxgi_half_to_float(src[x * 4 + 2]);
float lvl;
float nr = r * (80.0f / 10000.0f);
float ng = g * (80.0f / 10000.0f);
+5 -38
View File
@@ -9,8 +9,6 @@
#else
#define VT_ENCODE_AVAILABLE
#endif
#include "videotoolbox_encode_hardware.h"
typedef struct videotoolbox_encode_config
{
unsigned width, height, slots, bitrate, key_interval, timescale, bit_depth;
@@ -59,15 +57,7 @@ static INLINE VT_ENCODE_AVAILABLE videotoolbox_encode_t *videotoolbox_encode_new
videotoolbox_encode_t *encoder = NULL;
CFMutableDictionaryRef spec = NULL, attrs = NULL, props = NULL;
CFTypeRef hardware = NULL, selected_id = NULL;
CFStringRef admitted_id = NULL;
#ifdef VT_ENCODE_MOBILE
bool query_hardware = false;
#endif
OSStatus status = kVTParameterErr;
#ifdef VT_ENCODE_MOBILE
if (VT_ENCODE_HARDWARE_KEYS_AVAILABLE)
query_hardware = true;
#endif
if (error) *error = status;
if ((encoder_id && !CFStringGetLength(encoder_id)) || !config || !config->width || !config->height || (config->width & 1)
|| (config->height & 1) || config->width > 16384 || config->height > 16384
@@ -78,20 +68,6 @@ static INLINE VT_ENCODE_AVAILABLE videotoolbox_encode_t *videotoolbox_encode_new
|| (config->bit_depth != 8 && config->bit_depth != 10)
|| (config->bit_depth == 10 && !config->hevc)
|| (config->hdr && config->bit_depth != 10)) return NULL;
#ifdef VT_ENCODE_MOBILE
if (!query_hardware)
{
admitted_id = videotoolbox_encode_hardware_id(encoder_id,
config->hevc ? kCMVideoCodecType_HEVC : kCMVideoCodecType_H264);
if (!admitted_id)
{
if (error)
*error = kVTCouldNotFindVideoEncoderErr;
return NULL;
}
encoder_id = admitted_id;
}
#endif
encoder = (videotoolbox_encode_t*)calloc(1, sizeof(*encoder));
spec = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
attrs = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
@@ -100,10 +76,7 @@ static INLINE VT_ENCODE_AVAILABLE videotoolbox_encode_t *videotoolbox_encode_new
encoder->config = *config;
encoder->pool = videotoolbox_encode_slots_new(config->slots);
if (!encoder->pool) { status = kVTAllocationFailedErr; goto done; }
#ifdef VT_ENCODE_HAS_HARDWARE_KEYS
if (VT_ENCODE_HARDWARE_KEYS_AVAILABLE)
CFDictionarySetValue(spec, kVTVideoEncoderSpecification_RequireHardwareAcceleratedVideoEncoder, kCFBooleanTrue);
#endif
CFDictionarySetValue(spec, kVTVideoEncoderSpecification_RequireHardwareAcceleratedVideoEncoder, kCFBooleanTrue);
if (encoder_id) CFDictionarySetValue(spec,kVTVideoEncoderSpecification_EncoderID,encoder_id);
if (gpu_registry_id)
{
@@ -159,15 +132,10 @@ static INLINE VT_ENCODE_AVAILABLE videotoolbox_encode_t *videotoolbox_encode_new
if (status) goto done;
status = VTCompressionSessionPrepareToEncodeFrames(encoder->session);
if (status) goto done;
#ifdef VT_ENCODE_HAS_HARDWARE_KEYS
if (VT_ENCODE_HARDWARE_KEYS_AVAILABLE)
{
status = VTSessionCopyProperty(encoder->session,
kVTCompressionPropertyKey_UsingHardwareAcceleratedVideoEncoder, NULL, &hardware);
if (!status && (!hardware || CFGetTypeID(hardware) != CFBooleanGetTypeID()
|| !CFBooleanGetValue((CFBooleanRef)hardware))) status = kVTCouldNotFindVideoEncoderErr;
}
#endif
status = VTSessionCopyProperty(encoder->session,
kVTCompressionPropertyKey_UsingHardwareAcceleratedVideoEncoder, NULL, &hardware);
if (!status && (!hardware || CFGetTypeID(hardware) != CFBooleanGetTypeID()
|| !CFBooleanGetValue((CFBooleanRef)hardware))) status = kVTCouldNotFindVideoEncoderErr;
if (!status && encoder_id)
{
status=VTSessionCopyProperty(encoder->session,kVTCompressionPropertyKey_EncoderID,NULL,&selected_id);
@@ -175,7 +143,6 @@ static INLINE VT_ENCODE_AVAILABLE videotoolbox_encode_t *videotoolbox_encode_new
|| !CFEqual(selected_id,encoder_id))) status=kVTCouldNotFindVideoEncoderErr;
}
done:
if (admitted_id) CFRelease((CFTypeRef)admitted_id);
if (selected_id) CFRelease(selected_id);
if (hardware) CFRelease(hardware);
if (props) CFRelease(props);
-85
View File
@@ -1,85 +0,0 @@
/* Copyright (C) 2026 The RetroArch team. SPDX-License-Identifier: GPL-3.0-or-later */
#ifndef RETROARCH_VIDEOTOOLBOX_ENCODE_HARDWARE_H
#define RETROARCH_VIDEOTOOLBOX_ENCODE_HARDWARE_H
#if defined(__APPLE__) && !defined(VIDEOTOOLBOX_ENCODE_TEST_TYPES)
#include <TargetConditionals.h>
#if TARGET_OS_IPHONE
#define VT_ENCODE_MOBILE
#endif
#endif
#if !defined(VT_ENCODE_MOBILE) \
|| (defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && __IPHONE_OS_VERSION_MAX_ALLOWED >= 170400) \
|| (defined(__TV_OS_VERSION_MAX_ALLOWED) && __TV_OS_VERSION_MAX_ALLOWED >= 170400) \
|| (defined(__VISION_OS_VERSION_MAX_ALLOWED) && __VISION_OS_VERSION_MAX_ALLOWED >= 10100)
#define VT_ENCODE_HAS_HARDWARE_KEYS
#endif
#if defined(VT_ENCODE_MOBILE) && defined(VT_ENCODE_HAS_HARDWARE_KEYS)
#define VT_ENCODE_HARDWARE_KEYS_AVAILABLE \
__builtin_available(iOS 17.4, tvOS 17.4, macCatalyst 17.4, visionOS 1.1, *)
#elif defined(VT_ENCODE_HAS_HARDWARE_KEYS)
#define VT_ENCODE_HARDWARE_KEYS_AVAILABLE true
#else
#define VT_ENCODE_HARDWARE_KEYS_AVAILABLE false
#endif
#if defined(VT_ENCODE_MOBILE) || defined(VIDEOTOOLBOX_ENCODE_HARDWARE_LIST_TEST)
/* Cold admission only. Return a retained, advertised hardware encoder ID;
* the caller must independently confirm the session selected that same ID. */
static INLINE CFStringRef videotoolbox_encode_hardware_id(
CFStringRef requested, uint32_t codec_type)
{
#if defined(VIDEOTOOLBOX_ENCODE_HARDWARE_LIST_TEST) \
|| (defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && __IPHONE_OS_VERSION_MAX_ALLOWED >= 130000) \
|| (defined(__TV_OS_VERSION_MAX_ALLOWED) && __TV_OS_VERSION_MAX_ALLOWED >= 130000) \
|| defined(__VISION_OS_VERSION_MAX_ALLOWED)
#ifndef VIDEOTOOLBOX_ENCODE_HARDWARE_LIST_TEST
if (__builtin_available(iOS 13.0, tvOS 13.0, *))
#endif
{
CFArrayRef list = NULL;
CFStringRef selected = NULL;
CFIndex i, count;
OSStatus status = VTCopyVideoEncoderList(NULL, &list);
if (status || !list)
{
if (list)
CFRelease(list);
return NULL;
}
count = CFArrayGetCount(list);
if (count >= 0 && count <= 4096)
for (i = 0; i < count; i++)
{
CFDictionaryRef entry = (CFDictionaryRef)CFArrayGetValueAtIndex(list, i);
CFTypeRef hardware, codec, identifier;
int64_t value = 0;
if (!entry || CFGetTypeID(entry) != CFDictionaryGetTypeID())
continue;
hardware = CFDictionaryGetValue(entry, kVTVideoEncoderList_IsHardwareAccelerated);
codec = CFDictionaryGetValue(entry, kVTVideoEncoderList_CodecType);
identifier = CFDictionaryGetValue(entry, kVTVideoEncoderList_EncoderID);
if (!hardware || CFGetTypeID(hardware) != CFBooleanGetTypeID()
|| !CFBooleanGetValue((CFBooleanRef)hardware)
|| !codec || CFGetTypeID(codec) != CFNumberGetTypeID()
|| !CFNumberGetValue((CFNumberRef)codec, kCFNumberSInt64Type, &value)
|| value != (int64_t)codec_type
|| !identifier || CFGetTypeID(identifier) != CFStringGetTypeID()
|| !CFStringGetLength((CFStringRef)identifier)
|| (requested && !CFEqual(identifier, requested)))
continue;
selected = (CFStringRef)CFRetain(identifier);
break;
}
CFRelease(list);
return selected;
}
#endif
(void)requested;
(void)codec_type;
return NULL;
}
#endif
#endif
+2 -41
View File
@@ -482,52 +482,13 @@ static bool kms_display_server_crtc_vrr(int fd, uint32_t crtc_id)
return vrr;
}
/* Physical size comes from the connector (EDID or the panel's device
* tree node), pixel size from the live mode. The menu's touch drag,
* swipe and scaling need DPI; 0 mm means the sink did not say. */
static bool kms_display_server_geometry_metric(
enum display_metric_types type, float *value)
{
unsigned n;
switch (type)
{
case DISPLAY_METRIC_PIXEL_WIDTH:
n = g_drm_mode ? g_drm_mode->hdisplay : 0;
break;
case DISPLAY_METRIC_PIXEL_HEIGHT:
n = g_drm_mode ? g_drm_mode->vdisplay : 0;
break;
case DISPLAY_METRIC_MM_WIDTH:
n = g_drm_connector ? g_drm_connector->mmWidth : 0;
break;
case DISPLAY_METRIC_MM_HEIGHT:
n = g_drm_connector ? g_drm_connector->mmHeight : 0;
break;
case DISPLAY_METRIC_DPI:
if ( !g_drm_mode || !g_drm_mode->hdisplay
|| !g_drm_connector || !g_drm_connector->mmWidth)
return false;
*value = (float)g_drm_mode->hdisplay * 25.4f
/ (float)g_drm_connector->mmWidth;
return true;
default:
return false;
}
if (!n)
return false;
*value = (float)n;
return true;
}
static bool kms_display_server_get_metrics(void *data,
enum display_metric_types type, float *value)
{
bool vrr;
if (type != DISPLAY_METRIC_TOTAL_LINES)
return kms_display_server_geometry_metric(type, value);
if (!kms_display_server_mode_timed())
if ( type != DISPLAY_METRIC_TOTAL_LINES
|| !kms_display_server_mode_timed())
return false;
/* Read with the line count, outside Scanline Sync's wait */
vrr = g_crtc_id && kms_display_server_crtc_vrr(g_drm_fd, g_crtc_id);
+32 -4
View File
@@ -30,7 +30,6 @@
#include "../common/vulkan_video_import.h"
#include <retro_inline.h>
#include <retro_miscellaneous.h>
#include <math/float16.h>
#include <queues/mpsc_stack.h>
#include <queues/task_queue.h>
#include <retro_math.h>
@@ -17376,6 +17375,35 @@ static bool vulkan_read_viewport_bgrx(void *data, uint8_t *buffer,
}
#ifdef VULKAN_HDR_SWAPCHAIN
/* IEEE-754 half (binary16) -> float, for reading an RGBA16F scRGB backbuffer
* on the CPU. Handles normals, subnormals, sign and inf/nan. */
static float vulkan_half_to_float(uint16_t h)
{
uint32_t sign = (uint32_t)(h & 0x8000) << 16;
uint32_t exp = (h >> 10) & 0x1F;
uint32_t mant = h & 0x3FF;
uint32_t f;
float out;
if (exp == 0)
{
if (mant == 0)
f = sign;
else
{
exp = 127 - 15 + 1;
while (!(mant & 0x400)) { mant <<= 1; exp--; }
mant &= 0x3FF;
f = sign | (exp << 23) | (mant << 13);
}
}
else if (exp == 0x1F)
f = sign | 0x7F800000 | (mant << 13);
else
f = sign | ((exp - 15 + 127) << 23) | (mant << 13);
memcpy(&out, &f, sizeof(out));
return out;
}
/* ST.2084 (PQ) inverse-EOTF: normalised linear (v = nits/10000, [0,1]) ->
* PQ code [0,1]. Same constants as the forward HDR pipeline. */
static float vulkan_pq_encode(float v)
@@ -17561,9 +17589,9 @@ static bool vulkan_read_viewport_hdr(void *data, uint16_t *buffer,
int x;
for (x = 0; x < (int)vp_width; x++)
{
float r = retro_half_to_float(row[x * 4 + 0]);
float g = retro_half_to_float(row[x * 4 + 1]);
float b = retro_half_to_float(row[x * 4 + 2]);
float r = vulkan_half_to_float(row[x * 4 + 0]);
float g = vulkan_half_to_float(row[x * 4 + 1]);
float b = vulkan_half_to_float(row[x * 4 + 2]);
float lvl;
buffer[x * 3 + 0] = vulkan_scrgb_channel_to_pq16(r);
buffer[x * 3 + 1] = vulkan_scrgb_channel_to_pq16(g);
-19
View File
@@ -432,19 +432,6 @@ static bool android_gfx_ctx_destroy_surface(void *data)
#endif
}
#ifdef HAVE_EGL
/* A context in the share group, of the window's client API: OpenGL ES */
static bool android_gfx_ctx_shared_context_new(void *data,
gfx_ctx_shared_context_t *out)
{
android_ctx_data_t *and = (android_ctx_data_t*)data;
memset(out, 0, sizeof(*out));
if (!and || android_api != GFX_CTX_OPENGL_ES_API)
return false;
return egl_shared_context_new(&and->egl, EGL_OPENGL_ES_API, out);
}
#endif
const gfx_ctx_driver_t gfx_ctx_android = {
android_gfx_ctx_init,
android_gfx_ctx_destroy,
@@ -486,15 +473,9 @@ const gfx_ctx_driver_t gfx_ctx_android = {
NULL, /* presentable */
NULL, /* last_present_time */
android_gfx_ctx_release_current,
#ifdef HAVE_EGL
android_gfx_ctx_shared_context_new,
egl_shared_context_bind,
egl_shared_context_free,
#else
NULL, /* shared_context_new */
NULL, /* shared_context_bind */
NULL, /* shared_context_free */
#endif
#ifdef HAVE_EGL
&android_gfx_ctx_windows
#else
+1 -35
View File
@@ -1447,28 +1447,6 @@ static bool gfx_ctx_drm_destroy_surface(void *data)
#endif
}
#ifdef HAVE_EGL
/* A context in the share group, of the window's client API */
static bool gfx_ctx_drm_shared_context_new(void *data,
gfx_ctx_shared_context_t *out)
{
gfx_ctx_drm_data_t *drm = (gfx_ctx_drm_data_t*)data;
memset(out, 0, sizeof(*out));
if (!drm)
return false;
switch (drm_api)
{
case GFX_CTX_OPENGL_API:
return egl_shared_context_new(&drm->egl, EGL_OPENGL_API, out);
case GFX_CTX_OPENGL_ES_API:
return egl_shared_context_new(&drm->egl, EGL_OPENGL_ES_API, out);
default:
break;
}
return false;
}
#endif
const gfx_ctx_driver_t gfx_ctx_drm = {
gfx_ctx_drm_init,
gfx_ctx_drm_destroy,
@@ -1506,17 +1484,5 @@ const gfx_ctx_driver_t gfx_ctx_drm = {
NULL,
NULL,
gfx_ctx_drm_create_surface,
gfx_ctx_drm_destroy_surface,
NULL, /* presentable */
NULL, /* last_present_time */
NULL, /* release_current */
#ifdef HAVE_EGL
gfx_ctx_drm_shared_context_new,
egl_shared_context_bind,
egl_shared_context_free
#else
NULL, /* shared_context_new */
NULL, /* shared_context_bind */
NULL /* shared_context_free */
#endif
gfx_ctx_drm_destroy_surface
};
+1 -83
View File
@@ -152,10 +152,6 @@ static uint8_t wgl_flags;
#ifdef HAVE_EGL
static egl_ctx_data_t win32_egl;
#endif
/* The attributes the window's context was made with, for contexts in its
* share group (gfx_ctx_wgl_shared_context_new); none for a legacy one */
static int wgl_ctx_attribs[16];
static bool wgl_ctx_attribs_used = false;
static unsigned win32_major = 0;
static unsigned win32_minor = 0;
static int win32_interval = 0;
@@ -372,10 +368,6 @@ void create_gl_context(HWND hwnd, bool *quit)
}
}
for (i = 0; i < 16; i++)
wgl_ctx_attribs[i] = attribs[i];
wgl_ctx_attribs_used = true;
/* Found a suitable version that is high enough, we can stop now */
break;
}
@@ -827,71 +819,6 @@ static void gfx_ctx_wgl_release_current(void *data)
}
}
#if (defined(HAVE_OPENGL) || defined(HAVE_OPENGL1) || defined(HAVE_OPENGL_CORE)) && !defined(HAVE_OPENGLES)
/* A context in the share group of the one current on this thread - the
* core's, or the window's - with the window's attributes, for a thread
* of its own. It is made current on the window's device context: it
* draws into framebuffers of its own, never into the window. */
static bool gfx_ctx_wgl_shared_context_new(void *data,
gfx_ctx_shared_context_t *out)
{
typedef HGLRC (APIENTRY *wglCreateContextAttribsProc)
(HDC, HGLRC, const int*);
HGLRC share = wglGetCurrentContext();
HGLRC ctx = NULL;
memset(out, 0, sizeof(*out));
if (win32_api != GFX_CTX_OPENGL_API || !win32_hdc || !win32_hrc)
return false;
if (!share)
share = win32_hw_hrc ? win32_hw_hrc : win32_hrc;
if (wgl_ctx_attribs_used)
{
wglCreateContextAttribsProc create = (wglCreateContextAttribsProc)
gfx_ctx_wgl_get_proc_address("wglCreateContextAttribsARB");
if (create)
ctx = create(win32_hdc, share, wgl_ctx_attribs);
}
else if ((ctx = wglCreateContext(win32_hdc)) && !wglShareLists(share, ctx))
{
wglDeleteContext(ctx);
ctx = NULL;
}
if (!ctx)
{
RARCH_ERR("[WGL] A shared context could not be made: 0x%08lx.\n",
(unsigned long)GetLastError());
return false;
}
out->kind = GFX_CTX_SHARED_WGL;
out->context = ctx;
out->get_proc_address = gfx_ctx_wgl_get_proc_address;
return true;
}
static bool gfx_ctx_wgl_shared_context_bind(gfx_ctx_shared_context_t *ctx,
bool bind)
{
if (ctx->kind != GFX_CTX_SHARED_WGL)
return false;
if (!bind)
return wglMakeCurrent(NULL, NULL) ? true : false;
/* The window's, read now: a window made again has another one, of the
* same pixel format */
return wglMakeCurrent(win32_hdc, (HGLRC)ctx->context) ? true : false;
}
static void gfx_ctx_wgl_shared_context_free(gfx_ctx_shared_context_t *ctx)
{
if (ctx->kind != GFX_CTX_SHARED_WGL)
return;
wglDeleteContext((HGLRC)ctx->context);
memset(ctx, 0, sizeof(*ctx));
}
#endif
static void gfx_ctx_wgl_bind_hw_render(void *data, bool enable)
{
switch (win32_api)
@@ -1131,14 +1058,5 @@ const gfx_ctx_driver_t gfx_ctx_wgl = {
gfx_ctx_wgl_destroy_surface,
gfx_ctx_wgl_presentable,
gfx_ctx_wgl_last_present_time,
gfx_ctx_wgl_release_current,
#if (defined(HAVE_OPENGL) || defined(HAVE_OPENGL1) || defined(HAVE_OPENGL_CORE)) && !defined(HAVE_OPENGLES)
gfx_ctx_wgl_shared_context_new,
gfx_ctx_wgl_shared_context_bind,
gfx_ctx_wgl_shared_context_free
#else
NULL, /* shared_context_new */
NULL, /* shared_context_bind */
NULL /* shared_context_free */
#endif
gfx_ctx_wgl_release_current
};
File diff suppressed because it is too large. Load diff
-81
View File
@@ -5102,87 +5102,6 @@ bool video_driver_hw_render_interface_kept(void)
return iface == video_hw_render_iface_held;
}
/* RETRO_ENVIRONMENT_GET_HW_SHARED_CONTEXT_INTERFACE: the context driver's
* contexts in the window context's share group, which the core's context
* is in too, handed to the core for threads of its own. Made at most a few
* times a session (one per thread of the core's), so each its own block. */
struct retro_hw_shared_context
{
gfx_ctx_shared_context_t shared;
};
static struct retro_hw_shared_context *RETRO_CALLCONV
video_hw_shared_context_create(void)
{
video_driver_state_t *video_st = &video_driver_st;
const gfx_ctx_driver_t *ctx = &video_st->current_video_context;
struct retro_hw_shared_context *out;
if ( !ctx->shared_context_new
|| !video_st->context_data
|| !(out = (struct retro_hw_shared_context*)calloc(1, sizeof(*out))))
return NULL;
if (!ctx->shared_context_new((void*)video_st->context_data, &out->shared))
{
free(out);
return NULL;
}
return out;
}
static bool RETRO_CALLCONV video_hw_shared_context_make_current(
struct retro_hw_shared_context *ctx, bool current)
{
const gfx_ctx_driver_t *drv = &video_driver_st.current_video_context;
if (!ctx || !drv->shared_context_bind)
return false;
return drv->shared_context_bind(&ctx->shared, current);
}
static void RETRO_CALLCONV video_hw_shared_context_destroy(
struct retro_hw_shared_context *ctx)
{
const gfx_ctx_driver_t *drv = &video_driver_st.current_video_context;
if (!ctx)
return;
if (drv->shared_context_free)
drv->shared_context_free(&ctx->shared);
free(ctx);
}
static const struct retro_hw_shared_context_interface
video_hw_shared_context_iface = {
RETRO_HW_SHARED_CONTEXT_INTERFACE_VERSION,
video_hw_shared_context_create,
video_hw_shared_context_make_current,
video_hw_shared_context_destroy
};
const struct retro_hw_shared_context_interface
*video_driver_hw_shared_context_interface(void)
{
video_driver_state_t *video_st = &video_driver_st;
const gfx_ctx_driver_t *ctx = &video_st->current_video_context;
switch (video_st->hw_render.context_type)
{
case RETRO_HW_CONTEXT_OPENGL:
case RETRO_HW_CONTEXT_OPENGL_CORE:
case RETRO_HW_CONTEXT_OPENGLES2:
case RETRO_HW_CONTEXT_OPENGLES3:
case RETRO_HW_CONTEXT_OPENGLES_VERSION:
break;
default:
return NULL;
}
if ( !video_st->context_data
|| !ctx->shared_context_new
|| !ctx->shared_context_bind
|| !ctx->shared_context_free)
return NULL;
return &video_hw_shared_context_iface;
}
bool video_driver_hw_context_moved(int before, bool shared)
{
return before != -1 && before != (shared ? 1 : 0);
+6 -15
View File
@@ -829,8 +829,7 @@ enum gfx_ctx_shared_kind
{
GFX_CTX_SHARED_NONE = 0,
GFX_CTX_SHARED_EGL,
GFX_CTX_SHARED_GLX,
GFX_CTX_SHARED_WGL
GFX_CTX_SHARED_GLX
};
/* A second context in the window context's share group, for a thread
@@ -842,7 +841,7 @@ typedef struct gfx_ctx_shared_context
enum gfx_ctx_shared_kind kind;
void *display; /* EGLDisplay, or the X Display */
void *config; /* EGLConfig, or GLXFBConfig */
void *context; /* EGLContext, GLXContext or HGLRC */
void *context; /* EGLContext, or GLXContext */
void *surface; /* EGL: its own pbuffer, NULL surfaceless */
unsigned long drawable; /* GLX: its own pbuffer */
unsigned visual_id; /* GLX: the config's visual */
@@ -1012,12 +1011,10 @@ typedef struct gfx_ctx_driver
void (*release_current)(void *data);
/* Optional, desktop GL: a context in the window context's share
* group (gfx_ctx_shared_context_t). New and free run on a thread
* with a context of the group current - the video thread with the
* window's, or a hardware core's thread with the core's
* (RETRO_ENVIRONMENT_GET_HW_SHARED_CONTEXT_INTERFACE) - and leave it
* so; bind and unbind run on the thread that uses the context, which
* never gets the window's surface. NULL where the driver has none. Placed
* group (gfx_ctx_shared_context_t). New and free run on the video
* thread with the window's context current, and leave it so; bind
* and unbind run on the thread that uses the context, which never
* gets the window's surface. NULL where the driver has none. Placed
* last, as above. */
bool (*shared_context_new)(void *data, gfx_ctx_shared_context_t *out);
bool (*shared_context_bind)(gfx_ctx_shared_context_t *ctx, bool bind);
@@ -2830,12 +2827,6 @@ void video_driver_cache_context_ack_set(void);
* restart - and the core has to be reset after all. True for a core
* that holds none. */
void video_driver_hw_render_interface_note(const struct retro_hw_render_interface *iface);
/* RETRO_ENVIRONMENT_GET_HW_SHARED_CONTEXT_INTERFACE's answer: NULL when the
* core's context is not OpenGL or the context driver cannot make contexts
* in its share group. */
const struct retro_hw_shared_context_interface
*video_driver_hw_shared_context_interface(void);
bool video_driver_hw_render_interface_kept(void);
/* Which of a GL driver's contexts a hardware core renders in: its own,
* shared with the driver's (@shared), or the driver's. Called by the
-19
View File
@@ -582,9 +582,6 @@ VIDEO IMAGE
#ifdef HAVE_RTGA
#include "../libretro-common/formats/tga/rtga.c"
#endif
#ifdef HAVE_RGIF
#include "../libretro-common/formats/gif/rgif.c"
#endif
#ifdef HAVE_IMAGEVIEWER
#include "../cores/libretro-imageviewer/image_core.c"
@@ -779,13 +776,6 @@ VIDEO DRIVER
#include "../gfx/drivers/d3d12.c"
#endif
#ifdef HAVE_MF_AUDIO
#include "../record/record_mf_audio.c"
#if defined(HAVE_D3D12) && defined(HAVE_RTMP) && defined(HAVE_RFLV)
#include "../record/record_stream_d3d12.c"
#endif
#endif
#if defined(HAVE_D3D10)
#include "../gfx/drivers/d3d10.c"
#endif
@@ -915,7 +905,6 @@ FONTS
#include "../gfx/font_driver.c"
#include "../libretro-common/gfx/font/rtt.c"
#include "../gfx/drivers_font_renderer/stb.c"
#if defined(HAVE_FREETYPE)
@@ -1751,12 +1740,6 @@ RECORDING
#include "../record/record_avfoundation_worker.c"
#include "../record/record_avfoundation_session.c"
#include "../libretro-common/formats/h265/rh265_sps_crop.c"
#if defined(HAVE_NETWORKING) && defined(HAVE_RTMP) && defined(HAVE_RFLV)
#include "../record/record_stream_vt.c"
#include "../record/record_stream_output_vt.c"
#include "../record/record_vt_packet.c"
#include "../libretro-common/net/net_wake.c"
#endif
#endif
#ifdef HAVE_FFMPEG
#include "../record/drivers/record_ffmpeg.c"
@@ -1804,7 +1787,6 @@ NETPLAY
#include "../network/netplay/netplay_room_parse.c"
#include "../libretro-common/net/net_compat.c"
#include "../libretro-common/net/net_socket.c"
#include "../libretro-common/net/net_resolve.c"
#include "../libretro-common/net/net_http.c"
#ifdef HAVE_RTMP
#include "../libretro-common/net/net_rtmp_chunk.c"
@@ -1816,7 +1798,6 @@ NETPLAY
#include "../libretro-common/net/net_rtmp_reply.c"
#include "../libretro-common/net/net_rtmp_session.c"
#include "../libretro-common/net/net_rtmp_socket.c"
#include "../libretro-common/net/net_rtmp_client.c"
#endif
#ifdef HAVE_IFINFO
#include "../libretro-common/net/net_ifinfo.c"
-4
View File
@@ -74,7 +74,6 @@
#endif
#ifdef HAVE_AVF
#include "../record/record_at_audio.c"
#include "../camera/drivers/avfoundation.m"
#include "../record/drivers/record_avfoundation.m"
#endif
@@ -85,9 +84,6 @@
#include "../record/record_gpu_capture_metal.m"
#include "../record/record_mux_avfoundation.m"
#include "../record/record_gpu_session_metal.m"
#if defined(HAVE_NETWORKING) && defined(HAVE_RTMP) && defined(HAVE_RFLV)
#include "../record/record_at_resample.c"
#endif
#include "../record/record_gpu_dispatch_metal.m"
#endif
#endif
+34 -65
View File
@@ -514,9 +514,6 @@ typedef struct
bool run_state_update;
/* Touch panel properties */
bool is_touch_device;
/* Contacts come in MT slots; the single-touch emulation
* (ABS_X/ABS_Y/BTN_TOUCH) repeats one of them and is ignored. */
bool mt_slots;
} udev_input_touch_t;
#endif
@@ -718,6 +715,7 @@ static bool udev_vp_ok;
static udev_input_mouse_t *udev_get_mouse(
struct udev_input *udev, unsigned port)
{
unsigned i;
unsigned mouse_index = 0;
int dev_index = -1;
@@ -1133,8 +1131,10 @@ static void udev_touch_ts_print(const udev_touch_ts_t *ts)
static udev_input_device_t *udev_get_pointer_port_dev(
struct udev_input *udev, unsigned port)
{
uint16_t i;
uint16_t pointer_index = 0;
int16_t dev_index = -1;
udev_input_mouse_t *mouse = NULL;
if (port >= MAX_USERS || !video_driver_has_focus())
return NULL;
@@ -1506,19 +1506,13 @@ static void udev_init_touch_dev(udev_input_device_t *dev)
{
RARCH_WARN("[udev] Failed to get touchscreen limits.\n");
/* One slot, fed by the single-touch events */
memset(&abs_info, 0, sizeof(abs_info));
udev_touch_set_limits_from(&abs_info, &touch->info_slots);
touch->info_slots.enabled = false;
}
else
udev_touch_set_limits_from(&abs_info, &touch->info_slots);
touch->mt_slots = touch->info_slots.enabled
&& touch->info_slots.range > 1;
/* Single-touch devices use ABS_X/Y, Multi-touch use ABS_MT_POSITION_X/Y */
if (!touch->mt_slots)
if (abs_info.maximum == 0)
{
/* TODO - Test for single-touch devices. */
RARCH_WARN("[udev] Single-touch devices are currently untested.\n");
@@ -1614,15 +1608,9 @@ static void udev_init_touch_dev(udev_input_device_t *dev)
udev_destroy_touch_dev(dev);
return;
}
for (iii = 0; iii < touch->info_slots.range; ++iii)
{
touch->staging[iii].tracking_id = UDEV_INPUT_TOUCH_TRACKING_ID_NONE;
touch->current[iii].tracking_id = UDEV_INPUT_TOUCH_TRACKING_ID_NONE;
}
/* Initialize touch device; the kernel starts on slot 0 and does
* not announce it */
touch->current_slot = 0;
/* Initialize touch device */
touch->current_slot = UDEV_INPUT_TOUCH_SLOT_ID_NONE;
touch->is_touch_device = true;
touch->run_state_update = false;
udev_touch_ts_now(&touch->last_state_update);
@@ -1723,7 +1711,7 @@ static void udev_sync_touch(udev_input_device_t *dev)
int32_t *mt_req_values;
uint8_t *mt_request_data;
size_t mt_request_data_size;
int slot_count;
size_t slot_count;
udev_touch_ts_t now;
udev_input_touch_t *touch = &dev->touch;
udev_slot_state_t *staging = dev->touch.staging;
@@ -1766,11 +1754,6 @@ static void udev_sync_touch(udev_input_device_t *dev)
staging[iii].tracking_id = mt_req_values[iii];
udev_touch_ts_copy(&now, &staging[iii].td_time);
}
/* Contacts begun or ended unseen are counted as they are now */
touch->staging_active = 0;
for (iii = 0; iii < slot_count; ++iii)
if (staging[iii].tracking_id >= 0)
touch->staging_active++;
/* Request MT position on the x-axis for each slot */
*mt_req_code = ABS_MT_POSITION_X;
@@ -1873,8 +1856,8 @@ static bool udev_translate_touch_pos(
* One way to fix this is to add or remove 0.5, but this needs floating
* point operations which might not be desirable.
*/
int32_t ma_pos_x = (((((pointer_pos_x - src_touch->info_x_limits.min) * 0x7fff) / src_touch->info_x_limits.range) * VIDEO_SCALE_W(target_vp->full_dims)) / 0x7fff);
int32_t ma_pos_y = (((((pointer_pos_y - src_touch->info_y_limits.min) * 0x7fff) / src_touch->info_y_limits.range) * VIDEO_SCALE_H(target_vp->full_dims)) / 0x7fff);
int32_t ma_pos_x = (((((pointer_pos_x + src_touch->info_x_limits.min) * 0x7fff) / src_touch->info_x_limits.range) * VIDEO_SCALE_W(target_vp->full_dims)) / 0x7fff);
int32_t ma_pos_y = (((((pointer_pos_y + src_touch->info_y_limits.min) * 0x7fff) / src_touch->info_y_limits.range) * VIDEO_SCALE_H(target_vp->full_dims)) / 0x7fff);
/* Calculate relative offsets. */
VIDEO_POS_ADD(*pointer_ma_rel, ma_pos_x - VIDEO_POS_X(*pointer_ma_pos),
@@ -2407,7 +2390,7 @@ static void udev_report_touch(udev_input_t *udev, udev_input_device_t *dev)
/* Simulated pointer */
/* Release the pointer only after all contacts are released */
if (touch->pointer_enabled)
touch->pointer_btn_pp = (touch->staging_active > 0);
touch->pointer_btn_pp = (touch->staging_active == 0);
/* Mouse section */
if (touch->mouse_enabled)
@@ -2620,8 +2603,8 @@ static void udev_handle_touch(void *data,
const struct input_event *event, udev_input_device_t *dev)
{
udev_input_t *udev = (udev_input_t*)data;
udev_input_mouse_t *mouse = &dev->mouse;
udev_input_touch_t *touch = &dev->touch;
udev_slot_state_t *st0 = touch->staging;
/* struct input_event */
/* { */
@@ -2674,18 +2657,16 @@ static void udev_handle_touch(void *data,
}
break;
case ABS_X:
/* Single-touch contact, kept in slot 0 */
if (touch->mt_slots)
break;
/* TODO - Currently using single-touch events as touch with id 0 */
RARCH_DDBG("[udev] handle_touch: [0] ST_X to %d\n", event->value);
VIDEO_POS_PUT_X(st0->pos, event->value);
VIDEO_POS_PUT_X(touch->staging[0].pos, event->value);
/* Low priority event, mark the change. */
if (touch->staging[0].change == UDEV_TOUCH_CHANGE_NONE)
touch->staging[0].change = UDEV_TOUCH_CHANGE_MOVE;
/* Starting tracing, remember touchdown position. */
if (st0->change == UDEV_TOUCH_CHANGE_DOWN)
VIDEO_POS_PUT_X(st0->td_pos, event->value);
/* Low priority event, mark the change of a held contact. */
else if (st0->change == UDEV_TOUCH_CHANGE_NONE
&& st0->tracking_id >= 0)
st0->change = UDEV_TOUCH_CHANGE_MOVE;
else if (touch->staging[0].change == UDEV_TOUCH_CHANGE_DOWN)
VIDEO_POS_PUT_X(touch->staging[0].td_pos, event->value);
break;
case ABS_MT_POSITION_X:
RARCH_DDBG("[udev] handle_touch: [%d] MT_X to %d\n", touch->current_slot, event->value);
@@ -2698,15 +2679,15 @@ static void udev_handle_touch(void *data,
VIDEO_POS_PUT_X(touch->staging[touch->current_slot].td_pos, event->value);
break;
case ABS_Y:
if (touch->mt_slots)
break;
/* TODO - Currently using single-touch events as touch with id 0 */
RARCH_DDBG("[udev] handle_touch: [0] ST_Y to %d\n", event->value);
VIDEO_POS_PUT_Y(st0->pos, event->value);
if (st0->change == UDEV_TOUCH_CHANGE_DOWN)
VIDEO_POS_PUT_Y(st0->td_pos, event->value);
else if (st0->change == UDEV_TOUCH_CHANGE_NONE
&& st0->tracking_id >= 0)
st0->change = UDEV_TOUCH_CHANGE_MOVE;
VIDEO_POS_PUT_Y(touch->staging[0].pos, event->value);
/* Low priority event, mark the change. */
if (touch->staging[0].change == UDEV_TOUCH_CHANGE_NONE)
touch->staging[0].change = UDEV_TOUCH_CHANGE_MOVE;
/* Starting tracing, remember touchdown position. */
else if (touch->staging[0].change == UDEV_TOUCH_CHANGE_DOWN)
VIDEO_POS_PUT_Y(touch->staging[0].td_pos, event->value);
break;
case ABS_MT_POSITION_Y:
RARCH_DDBG("[udev] handle_touch: [%d] MT_Y to %d\n", touch->current_slot, event->value);
@@ -2747,25 +2728,11 @@ static void udev_handle_touch(void *data,
case EV_KEY:
if (event->code == BTN_TOUCH)
{
/* Single-touch contact, kept in slot 0 */
if (touch->mt_slots)
break;
RARCH_DDBG("[udev] handle_touch: [0] TOUCH %d\n", event->value);
RARCH_DDBG("[udev] handle_touch: [%d] TOUCH %d\n", touch->current_slot, event->value);
if (event->value > 0)
{
if (st0->tracking_id < 0)
{
st0->tracking_id = 0;
st0->change = UDEV_TOUCH_CHANGE_DOWN;
st0->td_pos = st0->pos;
udev_touch_event_ts_copy(event, &st0->td_time);
}
}
else if (st0->tracking_id >= 0)
{
st0->tracking_id = UDEV_INPUT_TOUCH_TRACKING_ID_NONE;
st0->change = UDEV_TOUCH_CHANGE_UP;
}
touch->staging[touch->current_slot].change = UDEV_TOUCH_CHANGE_DOWN;
else
touch->staging[touch->current_slot].change = UDEV_TOUCH_CHANGE_UP;
break;
}
else
@@ -3069,7 +3036,8 @@ static int16_t udev_input_touch_state(
case RETRO_DEVICE_POINTER:
case RARCH_DEVICE_POINTER_SCREEN:
screen = (device == RARCH_DEVICE_POINTER_SCREEN);
screen = (device == RARCH_DEVICE_MOUSE_SCREEN);
break;
switch (id)
{
case RETRO_DEVICE_ID_POINTER_X:
@@ -3584,6 +3552,7 @@ static void udev_input_handle_hotplug(udev_input_t *udev)
const char *val_touchscreen = NULL;
const char *action = NULL;
const char *devnode = NULL;
int check = 0;
struct udev_device *dev = udev_monitor_receive_device(
udev->monitor);
+5 -1
View File
@@ -2349,6 +2349,7 @@ static const struct
char s_aa08c6d6[124];
#endif
#endif
char s_27aef25c[59];
#ifdef _3DS
char s_2873cef1[111];
char s_b4816da6[77];
@@ -9627,6 +9628,8 @@ static const struct
"\200\321\213\320\273\320\260\320\264\320\260\321\205",
#endif
#endif
"\320\237\320\276\321\210\321\203\320\272 \321\226 \320\277\320\260\320\264\320\273\321\203\321"
"\207\321\215\320\275\320\275\320\265 bluetooth-\320\277\321\200\321\213\320\273\320\260\320\264.",
#ifdef _3DS
"\320\232\320\260\321\202\320\260\320\273\320\276\320\263 \321\200\321\215\321\201\321\203\321"
"\200\321\201\320\260\321\236 \320\264\320\273\321\217 \320\275\321\226\320\266\320\275\321\217"
@@ -16512,7 +16515,7 @@ static const struct
* compiler that pads this struct fails here instead of
* misindexing at runtime. */
typedef char msg_hash_be_blob_check[
(sizeof(msg_hash_be_blob) == (259191u
(sizeof(msg_hash_be_blob) == (259250u
#ifdef ANDROID
+ 531u
#endif
@@ -19200,6 +19203,7 @@ static const msg_hash_id_t msg_hash_be_ids[] =
(msg_hash_id_t)MENU_ENUM_SUBLABEL_BLUETOOTH_ERTM_DISABLE,
#endif
#endif
(msg_hash_id_t)MENU_ENUM_SUBLABEL_BLUETOOTH_SETTINGS,
#ifdef _3DS
(msg_hash_id_t)MENU_ENUM_SUBLABEL_BOTTOM_ASSETS_DIRECTORY,
(msg_hash_id_t)MENU_ENUM_SUBLABEL_BOTTOM_FONT_COLOR_BLUE,
+4 -1
View File
@@ -2832,6 +2832,7 @@ static const struct
char s_aa08c6d6[89];
#endif
#endif
char s_27aef25c[46];
#ifdef _3DS
char s_2873cef1[107];
char s_b4816da6[57];
@@ -7955,6 +7956,7 @@ static const struct
"Desactiva el ERTM del senyal Bluetooth per corregir l'emparellament d'alguns dispositius",
#endif
#endif
"Escaneja dispositius bluetooth i connecta-hi.",
#ifdef _3DS
"Indica la carpeta de recursos de la pantalla inferior. La carpeta ha de tenir un fitxer \"bottom"
"_menu.png\".",
@@ -10910,7 +10912,7 @@ static const struct
* compiler that pads this struct fails here instead of
* misindexing at runtime. */
typedef char msg_hash_ca_blob_check[
(sizeof(msg_hash_ca_blob) == (243435u
(sizeof(msg_hash_ca_blob) == (243481u
#ifdef ANDROID
+ 281u
#endif
@@ -14283,6 +14285,7 @@ static const msg_hash_id_t msg_hash_ca_ids[] =
(msg_hash_id_t)MENU_ENUM_SUBLABEL_BLUETOOTH_ERTM_DISABLE,
#endif
#endif
(msg_hash_id_t)MENU_ENUM_SUBLABEL_BLUETOOTH_SETTINGS,
#ifdef _3DS
(msg_hash_id_t)MENU_ENUM_SUBLABEL_BOTTOM_ASSETS_DIRECTORY,
(msg_hash_id_t)MENU_ENUM_SUBLABEL_BOTTOM_FONT_COLOR_BLUE,
+5 -1
View File
@@ -2900,6 +2900,7 @@ static const struct
char s_aa08c6d6[49];
#endif
#endif
char s_27aef25c[37];
#ifdef _3DS
char s_2873cef1[64];
char s_b4816da6[45];
@@ -9184,6 +9185,8 @@ static const struct
"\237\220\344\272\233\350\256\276\345\244\207\347\232\204\351\205\215\345\257\271",
#endif
#endif
"\346\211\253\346\217\217\350\223\235\347\211\231\350\256\276\345\244\207\345\271\266\350\277\236"
"\346\216\245\345\256\203\344\273\254\343\200\202",
#ifdef _3DS
"\345\272\225\351\203\250\345\261\217\345\271\225\350\265\204\344\272\247\347\233\256\345\275\225"
"\343\200\202\347\233\256\345\275\225\345\277\205\351\241\273\345\214\205\345\220\253 \"bow_menu."
@@ -14971,7 +14974,7 @@ static const struct
* compiler that pads this struct fails here instead of
* misindexing at runtime. */
typedef char msg_hash_chs_blob_check[
(sizeof(msg_hash_chs_blob) == (182045u
(sizeof(msg_hash_chs_blob) == (182082u
#ifdef ANDROID
+ 220u
#endif
@@ -18438,6 +18441,7 @@ static const msg_hash_id_t msg_hash_chs_ids[] =
(msg_hash_id_t)MENU_ENUM_SUBLABEL_BLUETOOTH_ERTM_DISABLE,
#endif
#endif
(msg_hash_id_t)MENU_ENUM_SUBLABEL_BLUETOOTH_SETTINGS,
#ifdef _3DS
(msg_hash_id_t)MENU_ENUM_SUBLABEL_BOTTOM_ASSETS_DIRECTORY,
(msg_hash_id_t)MENU_ENUM_SUBLABEL_BOTTOM_FONT_COLOR_BLUE,
+5 -1
View File
@@ -2310,6 +2310,7 @@ static const struct
#ifdef HAVE_LAKKA
char s_2bab34b2[22];
#endif
char s_27aef25c[31];
#ifdef _3DS
char s_2873cef1[102];
char s_b4816da6[34];
@@ -6967,6 +6968,8 @@ static const struct
#ifdef HAVE_LAKKA
"\351\205\215\345\260\215\350\227\215\347\211\231\350\243\235\347\275\256\343\200\202",
#endif
"\346\216\203\346\217\217\350\227\215\347\211\231\350\243\235\347\275\256\344\270\246\351\200\243"
"\346\216\245\343\200\202",
#ifdef _3DS
"\350\250\255\345\256\232\344\270\213\350\236\242\345\271\225\347\232\204\351\201\270\345\226\256"
"\344\270\273\351\241\214\350\263\207\346\226\231\345\244\276\344\275\215\347\275\256, \350\263"
@@ -10474,7 +10477,7 @@ static const struct
* compiler that pads this struct fails here instead of
* misindexing at runtime. */
typedef char msg_hash_cht_blob_check[
(sizeof(msg_hash_cht_blob) == (120236u
(sizeof(msg_hash_cht_blob) == (120267u
#ifdef ANDROID
+ 157u
#endif
@@ -13089,6 +13092,7 @@ static const msg_hash_id_t msg_hash_cht_ids[] =
#ifdef HAVE_LAKKA
(msg_hash_id_t)MENU_ENUM_SUBLABEL_BLUETOOTH_ENABLE,
#endif
(msg_hash_id_t)MENU_ENUM_SUBLABEL_BLUETOOTH_SETTINGS,
#ifdef _3DS
(msg_hash_id_t)MENU_ENUM_SUBLABEL_BOTTOM_ASSETS_DIRECTORY,
(msg_hash_id_t)MENU_ENUM_SUBLABEL_BOTTOM_FONT_COLOR_BLUE,
+4 -1
View File
@@ -2268,6 +2268,7 @@ static const struct
char s_aa08c6d6[78];
#endif
#endif
char s_27aef25c[49];
#ifdef _3DS
char s_2873cef1[84];
char s_b4816da6[50];
@@ -6404,6 +6405,7 @@ static const struct
"\275ch za\305\231\303\255zen\303\255",
#endif
#endif
"Vyhledejte za\305\231\303\255zen\303\255 Bluetooth a p\305\231ipojte je.",
#ifdef _3DS
"Adres\303\241\305\231 aktiv na spodn\303\255 obrazovce. Adres\303\241\305\231 mus\303\255 obsaho"
"vat \"spodn\303\255_menu.png\".",
@@ -8808,7 +8810,7 @@ static const struct
* compiler that pads this struct fails here instead of
* misindexing at runtime. */
typedef char msg_hash_cs_blob_check[
(sizeof(msg_hash_cs_blob) == (161502u
(sizeof(msg_hash_cs_blob) == (161551u
#ifdef ANDROID
+ 390u
#endif
@@ -11427,6 +11429,7 @@ static const msg_hash_id_t msg_hash_cs_ids[] =
(msg_hash_id_t)MENU_ENUM_SUBLABEL_BLUETOOTH_ERTM_DISABLE,
#endif
#endif
(msg_hash_id_t)MENU_ENUM_SUBLABEL_BLUETOOTH_SETTINGS,
#ifdef _3DS
(msg_hash_id_t)MENU_ENUM_SUBLABEL_BOTTOM_ASSETS_DIRECTORY,
(msg_hash_id_t)MENU_ENUM_SUBLABEL_BOTTOM_FONT_COLOR_BLUE,
+4 -1
View File
@@ -2828,6 +2828,7 @@ static const struct
char s_aa08c6d6[74];
#endif
#endif
char s_27aef25c[55];
#ifdef _3DS
char s_2873cef1[84];
char s_b4816da6[52];
@@ -8045,6 +8046,7 @@ static const struct
"Bluetooth ERTM deaktivieren, um das Koppeln einiger Ger\303\244te zu verbessern",
#endif
#endif
"Nach Bluetoothger\303\244ten suchen und mit ihnen verbinden.",
#ifdef _3DS
"Unterer Bildschirm Asset Verzeichnis. Verzeichnis muss \"bottom_menu.png\" enthalten.",
"Blaue Schriftfarbe auf unteren Bildschirm anpassen.",
@@ -11187,7 +11189,7 @@ static const struct
* compiler that pads this struct fails here instead of
* misindexing at runtime. */
typedef char msg_hash_de_blob_check[
(sizeof(msg_hash_de_blob) == (255069u
(sizeof(msg_hash_de_blob) == (255124u
#ifdef ANDROID
+ 358u
#endif
@@ -14576,6 +14578,7 @@ static const msg_hash_id_t msg_hash_de_ids[] =
(msg_hash_id_t)MENU_ENUM_SUBLABEL_BLUETOOTH_ERTM_DISABLE,
#endif
#endif
(msg_hash_id_t)MENU_ENUM_SUBLABEL_BLUETOOTH_SETTINGS,
#ifdef _3DS
(msg_hash_id_t)MENU_ENUM_SUBLABEL_BOTTOM_ASSETS_DIRECTORY,
(msg_hash_id_t)MENU_ENUM_SUBLABEL_BOTTOM_FONT_COLOR_BLUE,
+4 -1
View File
@@ -264,6 +264,7 @@ static const struct
char s_3c3598a9[39];
char s_a8d552a7[43];
char s_6112ec7c[38];
char s_27aef25c[45];
#ifdef _3DS
char s_b4816da6[39];
char s_450ca36f[40];
@@ -811,6 +812,7 @@ static const struct
"Change audio synchronisation settings.",
"Load customised configuration at start-up.",
"Load customised controls at start-up.",
"Scan for Bluetooth devices and connect them.",
#ifdef _3DS
"Adjust bottom screen font blue colour.",
"Adjust bottom screen font green colour.",
@@ -1139,7 +1141,7 @@ static const struct
* compiler that pads this struct fails here instead of
* misindexing at runtime. */
typedef char msg_hash_en_blob_check[
(sizeof(msg_hash_en_blob) == (26177u
(sizeof(msg_hash_en_blob) == (26222u
#ifdef HAVE_LAKKA
+ 176u
#endif
@@ -1473,6 +1475,7 @@ static const msg_hash_id_t msg_hash_en_ids[] =
(msg_hash_id_t)MENU_ENUM_SUBLABEL_AUDIO_SYNCHRONIZATION_SETTINGS,
(msg_hash_id_t)MENU_ENUM_SUBLABEL_AUTO_OVERRIDES_ENABLE,
(msg_hash_id_t)MENU_ENUM_SUBLABEL_AUTO_REMAPS_ENABLE,
(msg_hash_id_t)MENU_ENUM_SUBLABEL_BLUETOOTH_SETTINGS,
#ifdef _3DS
(msg_hash_id_t)MENU_ENUM_SUBLABEL_BOTTOM_FONT_COLOR_BLUE,
(msg_hash_id_t)MENU_ENUM_SUBLABEL_BOTTOM_FONT_COLOR_GREEN,
+4 -1
View File
@@ -2539,6 +2539,7 @@ static const struct
char s_aa08c6d6[68];
#endif
#endif
char s_27aef25c[49];
#ifdef _3DS
char s_2873cef1[82];
char s_b4816da6[58];
@@ -6985,6 +6986,7 @@ static const struct
"Malebligi ERTM de Bluetooth por ripari kupladon de kelkaj aparatoj.",
#endif
#endif
"Ser\304\211i aparatojn kun bluetooth kaj konekti ilin.",
#ifdef _3DS
"Havaja dosierujo de malsupra ekrano. Dosierujo devas inkluzivi \"bottom_menu.png\".",
"Al\304\235ustigi la bluecon de la tiparo de la malsupra ekrano.",
@@ -9168,7 +9170,7 @@ static const struct
* compiler that pads this struct fails here instead of
* misindexing at runtime. */
typedef char msg_hash_eo_blob_check[
(sizeof(msg_hash_eo_blob) == (170740u
(sizeof(msg_hash_eo_blob) == (170789u
#ifdef ANDROID
+ 312u
#endif
@@ -12137,6 +12139,7 @@ static const msg_hash_id_t msg_hash_eo_ids[] =
(msg_hash_id_t)MENU_ENUM_SUBLABEL_BLUETOOTH_ERTM_DISABLE,
#endif
#endif
(msg_hash_id_t)MENU_ENUM_SUBLABEL_BLUETOOTH_SETTINGS,
#ifdef _3DS
(msg_hash_id_t)MENU_ENUM_SUBLABEL_BOTTOM_ASSETS_DIRECTORY,
(msg_hash_id_t)MENU_ENUM_SUBLABEL_BOTTOM_FONT_COLOR_BLUE,
+4 -1
View File
@@ -2939,6 +2939,7 @@ static const struct
char s_aa08c6d6[98];
#endif
#endif
char s_27aef25c[58];
#ifdef _3DS
char s_2873cef1[116];
char s_b4816da6[59];
@@ -8271,6 +8272,7 @@ static const struct
"itivos.",
#endif
#endif
"Busca dispositivos con Bluetooth para conectarse a ellos.",
#ifdef _3DS
"Indica el directorio de recursos de la pantalla inferior. El directorio debe contener el archivo"
" \"bottom_menu.png\".",
@@ -11518,7 +11520,7 @@ static const struct
* compiler that pads this struct fails here instead of
* misindexing at runtime. */
typedef char msg_hash_es_blob_check[
(sizeof(msg_hash_es_blob) == (272604u
(sizeof(msg_hash_es_blob) == (272662u
#ifdef ANDROID
+ 329u
#endif
@@ -15011,6 +15013,7 @@ static const msg_hash_id_t msg_hash_es_ids[] =
(msg_hash_id_t)MENU_ENUM_SUBLABEL_BLUETOOTH_ERTM_DISABLE,
#endif
#endif
(msg_hash_id_t)MENU_ENUM_SUBLABEL_BLUETOOTH_SETTINGS,
#ifdef _3DS
(msg_hash_id_t)MENU_ENUM_SUBLABEL_BOTTOM_ASSETS_DIRECTORY,
(msg_hash_id_t)MENU_ENUM_SUBLABEL_BOTTOM_FONT_COLOR_BLUE,
+4 -1
View File
@@ -2206,6 +2206,7 @@ static const struct
#ifdef HAVE_LAKKA
char s_2bab34b2[29];
#endif
char s_27aef25c[41];
#ifdef _3DS
char s_2873cef1[85];
char s_b4816da6[51];
@@ -5796,6 +5797,7 @@ static const struct
#ifdef HAVE_LAKKA
"M\303\244\303\244rit\303\244 bluetoothin tila.",
#endif
"Etsi bluetooth laitteita ja yhdist\303\244 ne.",
#ifdef _3DS
"Alemman n\303\244yt\303\266n resurssien kansio. Kansioon on sis\303\244llytett\303\244v\303\244 "
"\"bottom_menu.png\".",
@@ -7578,7 +7580,7 @@ static const struct
* compiler that pads this struct fails here instead of
* misindexing at runtime. */
typedef char msg_hash_fi_blob_check[
(sizeof(msg_hash_fi_blob) == (123429u
(sizeof(msg_hash_fi_blob) == (123470u
#ifdef HAVE_LAKKA
+ 257u
#endif
@@ -10109,6 +10111,7 @@ static const msg_hash_id_t msg_hash_fi_ids[] =
#ifdef HAVE_LAKKA
(msg_hash_id_t)MENU_ENUM_SUBLABEL_BLUETOOTH_ENABLE,
#endif
(msg_hash_id_t)MENU_ENUM_SUBLABEL_BLUETOOTH_SETTINGS,
#ifdef _3DS
(msg_hash_id_t)MENU_ENUM_SUBLABEL_BOTTOM_ASSETS_DIRECTORY,
(msg_hash_id_t)MENU_ENUM_SUBLABEL_BOTTOM_FONT_COLOR_BLUE,
+4 -1
View File
@@ -2801,6 +2801,7 @@ static const struct
char s_aa08c6d6[77];
#endif
#endif
char s_27aef25c[59];
#ifdef _3DS
char s_2873cef1[86];
char s_b4816da6[58];
@@ -7940,6 +7941,7 @@ static const struct
"D\303\251sactiver l'ERTM Bluetooth pour corriger l'appairage de certains appareils",
#endif
#endif
"Rechercher des p\303\251riph\303\251riques Bluetooth et les connecter.",
#ifdef _3DS
"Dossier des ressources de l'\303\251cran du bas. Le dossier doit inclure \"bottom_menu.png\".",
"Ajuster la couleur bleue de la police de l'\303\251cran du bas.",
@@ -11025,7 +11027,7 @@ static const struct
* compiler that pads this struct fails here instead of
* misindexing at runtime. */
typedef char msg_hash_fr_blob_check[
(sizeof(msg_hash_fr_blob) == (257548u
(sizeof(msg_hash_fr_blob) == (257607u
#ifdef ANDROID
+ 373u
#endif
@@ -14364,6 +14366,7 @@ static const msg_hash_id_t msg_hash_fr_ids[] =
(msg_hash_id_t)MENU_ENUM_SUBLABEL_BLUETOOTH_ERTM_DISABLE,
#endif
#endif
(msg_hash_id_t)MENU_ENUM_SUBLABEL_BLUETOOTH_SETTINGS,
#ifdef _3DS
(msg_hash_id_t)MENU_ENUM_SUBLABEL_BOTTOM_ASSETS_DIRECTORY,
(msg_hash_id_t)MENU_ENUM_SUBLABEL_BOTTOM_FONT_COLOR_BLUE,
+4 -39
View File
@@ -2546,10 +2546,6 @@ static const struct
char s_bb929824[28];
char s_fe2ec9bd[35];
char s_1e3a9360[40];
char s_5943aeda[30];
char s_60b84450[31];
char s_782f95e3[31];
char s_5081d7d8[37];
char s_5741c1d0[23];
char s_a1a7717d[24];
char s_e6ca3876[27];
@@ -2979,6 +2975,7 @@ static const struct
char s_aa08c6d6[73];
#endif
#endif
char s_27aef25c[61];
#ifdef _3DS
char s_2873cef1[90];
char s_b4816da6[48];
@@ -4224,10 +4221,6 @@ static const struct
char s_72e21512[263];
char s_9f6de46b[305];
char s_26e66ece[276];
char s_5f131848[172];
char s_23227a3e[167];
char s_87e08991[167];
char s_56660806[173];
char s_66f2b57e[54];
char s_a776daeb[87];
char s_88095324[87];
@@ -4290,7 +4283,6 @@ static const struct
char s_dc6f9d69[50];
char s_417085f4[57];
char s_1bcf70a7[185];
char s_fbed99aa[217];
char s_2e2ca41a[312];
char s_f48b1fac[55];
char s_f4ad1b37[100];
@@ -7975,10 +7967,6 @@ static const struct
"Leagan Amach Fo-phicteil\303\255n",
"\303\232s\303\241id an Buaicphointe Taispe\303\241na",
"D\303\255ch\303\263d\303\272 f\303\255se\303\241in tr\303\255 chrua-earra\303\255",
"Imeall an Sc\303\241ile\303\241in Bun (%)",
"Imill Chl\303\251 an Sc\303\241ile\303\241in (%)",
"Imill Sc\303\241ile\303\241in ar Dheis (%)",
"Imill an Sc\303\241ile\303\241in ag an mBarr (%)",
"Leagan Amach F\303\255se\303\241in",
"Uasmh\303\251id Moille Fr\303\241ma",
"Uasta \303\215omh\303\241nna Swapchain",
@@ -8568,6 +8556,7 @@ static const struct
"\303\272",
#endif
#endif
"Scan\303\241il le haghaidh gl\303\251asanna bluetooth agus ceangail iad.",
#ifdef _3DS
"Eolaire s\303\263cmhainn\303\255 bun an sc\303\241ile\303\241in. N\303\255 m\303\263r \"bottom_m"
"enu.png\" a bheith san eolaire.",
@@ -11110,18 +11099,6 @@ static const struct
" Vulkan), rud a fh\303\241gann an CPU saor; m\303\241 roghna\303\255tear 'Off', d\303\251antar i"
"ad a dh\303\255ch\303\263d\303\272 ar an CPU. Baineann s\303\251 seo le r\303\251amhamhairc a os"
"cla\303\255tear feasta.",
"F\303\241g sp\303\241s ag imeall \303\255ochtair an chluiche agus an roghchl\303\241ir, arna shl"
"oinneadh mar ch\303\251atad\303\241n den fhuinneog ar iOS. M\303\241 shocra\303\255tear \303\251"
" ar 0, n\303\255 bheidh aon imeall ann.",
"F\303\241g sp\303\241s ag imeall cl\303\251 an chluiche agus an roghchl\303\241ir, arna shloinne"
"adh mar ch\303\251atad\303\241n den fhuinneog ar iOS. M\303\241 shocra\303\255tear \303\251 ar 0"
", n\303\255 bheidh aon imeall ann.",
"F\303\241g sp\303\241s ag imeall deas an chluiche agus an roghchl\303\241ir, arna shloinneadh ma"
"r ch\303\251atad\303\241n den fhuinneog ar iOS. M\303\241 shocra\303\255tear \303\251 ar 0, n"
"\303\255 bheidh aon imeall ann.",
"F\303\241g sp\303\241s ag imeall uachtarach an chluiche agus an roghchl\303\241ir, arna shloinne"
"adh mar ch\303\251atad\303\241n den fhuinneog ar iOS. M\303\241 shocra\303\255tear \303\251 ar 0"
", n\303\255 bheidh aon imeall ann.",
"St\303\263r\303\241iltear Leagan Amach F\303\255se\303\241in san eolaire seo.",
"Ins\303\255onn s\303\251 don tiom\303\241na\303\255 f\303\255se modh maol\303\241naithe sonraith"
"e a \303\272s\303\241id go sainr\303\241ite.",
@@ -11320,10 +11297,6 @@ static const struct
"Coinn\303\255onn 'Ceangailte' an sc\303\241ile\303\241n seo in \303\251ineacht leis na cinn eile"
". Cuireann 'Ar leithligh' \303\251 ar fhuinneog n\303\263 ar thaispe\303\241int d\303\241 chuid "
"f\303\251in. F\303\241gann 'Faoi cheilt' ar l\303\241r \303\251.",
"C\303\241 dt\303\251ann an sc\303\241ile\303\241n seo nuair a bh\303\255onn a fhuinneog f\303"
"\251in aige? Roghna\303\255tear an dara taispe\303\241int go huathoibr\303\255och. Fanann an sc"
"\303\241ile\303\241n ceangailte leis an taispe\303\241int a bhfuil RetroArch \303\241 thaispe"
"\303\241int uirthi.",
"D\303\272n an roghchl\303\241r agus bog sc\303\241ile\303\241in agus roghchl\303\241r na gcluas"
"\303\241n leis na rialt\303\263ir\303\255: greama\303\255onn an greim, claonann an truicear, ath"
"ra\303\255onn an bata achar agus m\303\251id, casann agus claonann bata na l\303\241imhe saora, "
@@ -12431,7 +12404,7 @@ static const struct
* compiler that pads this struct fails here instead of
* misindexing at runtime. */
typedef char msg_hash_ga_blob_check[
(sizeof(msg_hash_ga_blob) == (274061u
(sizeof(msg_hash_ga_blob) == (273097u
#ifdef ANDROID
+ 390u
#endif
@@ -15532,10 +15505,6 @@ static const msg_hash_id_t msg_hash_ga_ids[] =
(msg_hash_id_t)MENU_ENUM_LABEL_VALUE_VIDEO_HDR_SUBPIXEL_LAYOUT,
(msg_hash_id_t)MENU_ENUM_LABEL_VALUE_VIDEO_HDR_USE_DISPLAY_PEAK,
(msg_hash_id_t)MENU_ENUM_LABEL_VALUE_VIDEO_HW_DECODE,
(msg_hash_id_t)MENU_ENUM_LABEL_VALUE_VIDEO_IOS_MARGIN_BOTTOM,
(msg_hash_id_t)MENU_ENUM_LABEL_VALUE_VIDEO_IOS_MARGIN_LEFT,
(msg_hash_id_t)MENU_ENUM_LABEL_VALUE_VIDEO_IOS_MARGIN_RIGHT,
(msg_hash_id_t)MENU_ENUM_LABEL_VALUE_VIDEO_IOS_MARGIN_TOP,
(msg_hash_id_t)MENU_ENUM_LABEL_VALUE_VIDEO_LAYOUT_DIRECTORY,
(msg_hash_id_t)MENU_ENUM_LABEL_VALUE_VIDEO_MAX_FRAME_LATENCY,
(msg_hash_id_t)MENU_ENUM_LABEL_VALUE_VIDEO_MAX_SWAPCHAIN_IMAGES,
@@ -15957,6 +15926,7 @@ static const msg_hash_id_t msg_hash_ga_ids[] =
(msg_hash_id_t)MENU_ENUM_SUBLABEL_BLUETOOTH_ERTM_DISABLE,
#endif
#endif
(msg_hash_id_t)MENU_ENUM_SUBLABEL_BLUETOOTH_SETTINGS,
#ifdef _3DS
(msg_hash_id_t)MENU_ENUM_SUBLABEL_BOTTOM_ASSETS_DIRECTORY,
(msg_hash_id_t)MENU_ENUM_SUBLABEL_BOTTOM_FONT_COLOR_BLUE,
@@ -17192,10 +17162,6 @@ static const msg_hash_id_t msg_hash_ga_ids[] =
(msg_hash_id_t)MENU_ENUM_SUBLABEL_VIDEO_HDR_SUBPIXEL_LAYOUT,
(msg_hash_id_t)MENU_ENUM_SUBLABEL_VIDEO_HDR_USE_DISPLAY_PEAK,
(msg_hash_id_t)MENU_ENUM_SUBLABEL_VIDEO_HW_DECODE,
(msg_hash_id_t)MENU_ENUM_SUBLABEL_VIDEO_IOS_MARGIN_BOTTOM,
(msg_hash_id_t)MENU_ENUM_SUBLABEL_VIDEO_IOS_MARGIN_LEFT,
(msg_hash_id_t)MENU_ENUM_SUBLABEL_VIDEO_IOS_MARGIN_RIGHT,
(msg_hash_id_t)MENU_ENUM_SUBLABEL_VIDEO_IOS_MARGIN_TOP,
(msg_hash_id_t)MENU_ENUM_SUBLABEL_VIDEO_LAYOUT_DIRECTORY,
(msg_hash_id_t)MENU_ENUM_SUBLABEL_VIDEO_MAX_FRAME_LATENCY,
(msg_hash_id_t)MENU_ENUM_SUBLABEL_VIDEO_MAX_SWAPCHAIN_IMAGES,
@@ -17258,7 +17224,6 @@ static const msg_hash_id_t msg_hash_ga_ids[] =
(msg_hash_id_t)MENU_ENUM_SUBLABEL_VIDEO_SCREEN_LAYOUT,
(msg_hash_id_t)MENU_ENUM_SUBLABEL_VIDEO_SCREEN_SELECTED,
(msg_hash_id_t)MENU_ENUM_SUBLABEL_VIDEO_SCREEN_WINDOW_MODE,
(msg_hash_id_t)MENU_ENUM_SUBLABEL_VIDEO_SCREEN_WINDOW_MONITOR,
(msg_hash_id_t)MENU_ENUM_SUBLABEL_VIDEO_SCREEN_XR_EDIT,
(msg_hash_id_t)MENU_ENUM_SUBLABEL_VIDEO_SCREEN_XR_PITCH,
(msg_hash_id_t)MENU_ENUM_SUBLABEL_VIDEO_SCREEN_XR_RESET,
+4 -1
View File
@@ -2615,6 +2615,7 @@ static const struct
char s_aa08c6d6[78];
#endif
#endif
char s_27aef25c[43];
#ifdef _3DS
char s_2873cef1[90];
char s_450ca36f[50];
@@ -7314,6 +7315,7 @@ static const struct
"Desactiva o Bluetooth ERTM para corrixir a vinculaci\303\263n dalg\303\272ns dispositivos",
#endif
#endif
"Busca dispositivos bluetooth e con\303\251ctaos.",
#ifdef _3DS
"Directorio de activos da pantalla inferior. O directorio debe inclu\303\255r \"bottom_menu.png\""
".",
@@ -9792,7 +9794,7 @@ static const struct
* compiler that pads this struct fails here instead of
* misindexing at runtime. */
typedef char msg_hash_gl_blob_check[
(sizeof(msg_hash_gl_blob) == (210874u
(sizeof(msg_hash_gl_blob) == (210917u
#ifdef ANDROID
+ 365u
#endif
@@ -12847,6 +12849,7 @@ static const msg_hash_id_t msg_hash_gl_ids[] =
(msg_hash_id_t)MENU_ENUM_SUBLABEL_BLUETOOTH_ERTM_DISABLE,
#endif
#endif
(msg_hash_id_t)MENU_ENUM_SUBLABEL_BLUETOOTH_SETTINGS,
#ifdef _3DS
(msg_hash_id_t)MENU_ENUM_SUBLABEL_BOTTOM_ASSETS_DIRECTORY,
(msg_hash_id_t)MENU_ENUM_SUBLABEL_BOTTOM_FONT_COLOR_GREEN,
+4 -1
View File
@@ -2455,6 +2455,7 @@ static const struct
char s_aa08c6d6[83];
#endif
#endif
char s_27aef25c[53];
#ifdef _3DS
char s_2873cef1[104];
char s_b4816da6[53];
@@ -7022,6 +7023,7 @@ static const struct
"\241ros\303\255t\303\241s\303\241n\303\241l",
#endif
#endif
"Bluetooth eszk\303\266z\303\266k keres\303\251se \303\251s csatlakoztat\303\241sa.",
#ifdef _3DS
"Az als\303\263 k\303\251perny\305\221 be\303\251p\303\255tett m\303\251diaf\303\241jljainak k"
"\303\266nyvt\303\241ra. A \"bottom_menu.png\" meg kell legyen itt.",
@@ -9814,7 +9816,7 @@ static const struct
* compiler that pads this struct fails here instead of
* misindexing at runtime. */
typedef char msg_hash_hu_blob_check[
(sizeof(msg_hash_hu_blob) == (187136u
(sizeof(msg_hash_hu_blob) == (187189u
#ifdef ANDROID
+ 316u
#endif
@@ -12697,6 +12699,7 @@ static const msg_hash_id_t msg_hash_hu_ids[] =
(msg_hash_id_t)MENU_ENUM_SUBLABEL_BLUETOOTH_ERTM_DISABLE,
#endif
#endif
(msg_hash_id_t)MENU_ENUM_SUBLABEL_BLUETOOTH_SETTINGS,
#ifdef _3DS
(msg_hash_id_t)MENU_ENUM_SUBLABEL_BOTTOM_ASSETS_DIRECTORY,
(msg_hash_id_t)MENU_ENUM_SUBLABEL_BOTTOM_FONT_COLOR_BLUE,
+4 -1
View File
@@ -2429,6 +2429,7 @@ static const struct
char s_aa08c6d6[81];
#endif
#endif
char s_27aef25c[52];
#ifdef _3DS
char s_2873cef1[88];
char s_b4816da6[55];
@@ -6712,6 +6713,7 @@ static const struct
"Disabilita l'ERTM Bluetooth per correggere l'accoppiamento di alcuni dispositivi",
#endif
#endif
"Scansione per i dispositivi bluetooth e collegarli.",
#ifdef _3DS
"Directory asset nello schermo inferiore. La directory deve includere \"bottom_menu.png\".",
"Regola il colore blu del font dello schermo inferiore.",
@@ -8838,7 +8840,7 @@ static const struct
* compiler that pads this struct fails here instead of
* misindexing at runtime. */
typedef char msg_hash_it_blob_check[
(sizeof(msg_hash_it_blob) == (182260u
(sizeof(msg_hash_it_blob) == (182312u
#ifdef ANDROID
+ 376u
#endif
@@ -11698,6 +11700,7 @@ static const msg_hash_id_t msg_hash_it_ids[] =
(msg_hash_id_t)MENU_ENUM_SUBLABEL_BLUETOOTH_ERTM_DISABLE,
#endif
#endif
(msg_hash_id_t)MENU_ENUM_SUBLABEL_BLUETOOTH_SETTINGS,
#ifdef _3DS
(msg_hash_id_t)MENU_ENUM_SUBLABEL_BOTTOM_ASSETS_DIRECTORY,
(msg_hash_id_t)MENU_ENUM_SUBLABEL_BOTTOM_FONT_COLOR_BLUE,
+6 -1
View File
@@ -2250,6 +2250,7 @@ static const struct
char s_aa08c6d6[82];
#endif
#endif
char s_27aef25c[62];
#ifdef _3DS
char s_2873cef1[133];
char s_b4816da6[55];
@@ -8156,6 +8157,9 @@ static const struct
"\263\343\202\260\343\202\222\344\277\256\346\255\243\343\201\227\343\201\276\343\201\231",
#endif
#endif
"Bluetooth \343\203\207\343\203\220\343\202\244\343\202\271\343\202\222\343\202\271\343\202\255"
"\343\203\243\343\203\263\343\201\227\343\201\246\346\216\245\347\266\232\343\201\227\343\201\276"
"\343\201\231\343\200\202",
#ifdef _3DS
"\344\270\213\347\224\273\351\235\242\343\202\242\343\202\273\343\203\203\343\203\210\343\201\256"
"\343\203\207\343\202\243\343\203\254\343\202\257\343\203\210\343\203\252\343\201\247\343\201\231"
@@ -13928,7 +13932,7 @@ static const struct
* compiler that pads this struct fails here instead of
* misindexing at runtime. */
typedef char msg_hash_ja_blob_check[
(sizeof(msg_hash_ja_blob) == (199220u
(sizeof(msg_hash_ja_blob) == (199282u
#ifdef ANDROID
+ 484u
#endif
@@ -16504,6 +16508,7 @@ static const msg_hash_id_t msg_hash_ja_ids[] =
(msg_hash_id_t)MENU_ENUM_SUBLABEL_BLUETOOTH_ERTM_DISABLE,
#endif
#endif
(msg_hash_id_t)MENU_ENUM_SUBLABEL_BLUETOOTH_SETTINGS,
#ifdef _3DS
(msg_hash_id_t)MENU_ENUM_SUBLABEL_BOTTOM_ASSETS_DIRECTORY,
(msg_hash_id_t)MENU_ENUM_SUBLABEL_BOTTOM_FONT_COLOR_BLUE,
+6 -1
View File
@@ -2808,6 +2808,7 @@ static const struct
char s_aa08c6d6[121];
#endif
#endif
char s_27aef25c[53];
#ifdef _3DS
char s_2873cef1[122];
char s_b4816da6[54];
@@ -9659,6 +9660,9 @@ static const struct
"\210\230 \354\236\210\354\212\265\353\213\210\353\213\244",
#endif
#endif
"\353\270\224\353\243\250\355\210\254\354\212\244 \354\236\245\353\271\204\353\245\274 \352\262"
"\200\354\203\211\355\225\230\352\263\240 \354\227\260\352\262\260\355\225\251\353\213\210\353"
"\213\244.",
#ifdef _3DS
"\354\225\204\353\236\230 \355\231\224\353\251\264 \354\225\240\354\205\213 \353\224\224\353\240"
"\211\355\206\240\353\246\254\354\236\205\353\213\210\353\213\244. \353\224\224\353\240\211\355"
@@ -16219,7 +16223,7 @@ static const struct
* compiler that pads this struct fails here instead of
* misindexing at runtime. */
typedef char msg_hash_ko_blob_check[
(sizeof(msg_hash_ko_blob) == (228924u
(sizeof(msg_hash_ko_blob) == (228977u
#ifdef ANDROID
+ 436u
#endif
@@ -19488,6 +19492,7 @@ static const msg_hash_id_t msg_hash_ko_ids[] =
(msg_hash_id_t)MENU_ENUM_SUBLABEL_BLUETOOTH_ERTM_DISABLE,
#endif
#endif
(msg_hash_id_t)MENU_ENUM_SUBLABEL_BLUETOOTH_SETTINGS,
#ifdef _3DS
(msg_hash_id_t)MENU_ENUM_SUBLABEL_BOTTOM_ASSETS_DIRECTORY,
(msg_hash_id_t)MENU_ENUM_SUBLABEL_BOTTOM_FONT_COLOR_BLUE,
+4 -1
View File
@@ -2381,6 +2381,7 @@ static const struct
char s_aa08c6d6[78];
#endif
#endif
char s_27aef25c[45];
#ifdef _3DS
char s_2873cef1[76];
char s_b4816da6[64];
@@ -6580,6 +6581,7 @@ static const struct
"Schakel Bluetooth ERTM uit om de koppeling van sommige apparaten te repareren",
#endif
#endif
"Scan naar bluetooth apparaten en verbind ze.",
#ifdef _3DS
"De map met assets voor het onderste scherm moet \"bottom_menu.png\" bevatten.",
"Pas de blauwe kleur van het lettertype onderaan het scherm aan.",
@@ -8650,7 +8652,7 @@ static const struct
* compiler that pads this struct fails here instead of
* misindexing at runtime. */
typedef char msg_hash_nl_blob_check[
(sizeof(msg_hash_nl_blob) == (172383u
(sizeof(msg_hash_nl_blob) == (172428u
#ifdef ANDROID
+ 375u
#endif
@@ -11464,6 +11466,7 @@ static const msg_hash_id_t msg_hash_nl_ids[] =
(msg_hash_id_t)MENU_ENUM_SUBLABEL_BLUETOOTH_ERTM_DISABLE,
#endif
#endif
(msg_hash_id_t)MENU_ENUM_SUBLABEL_BLUETOOTH_SETTINGS,
#ifdef _3DS
(msg_hash_id_t)MENU_ENUM_SUBLABEL_BOTTOM_ASSETS_DIRECTORY,
(msg_hash_id_t)MENU_ENUM_SUBLABEL_BOTTOM_FONT_COLOR_BLUE,
+4 -1
View File
@@ -924,6 +924,7 @@ static const struct
char s_8a24406f[28];
char s_5977d6d8[44];
char s_f6adf4ee[39];
char s_27aef25c[53];
#ifdef _3DS
char s_f441f728[37];
#endif
@@ -2207,6 +2208,7 @@ static const struct
"Demp all lyd i stillemodus.",
"Endre innstillinger for lyd inngang/utgang.",
"Vis n\303\245v\303\246rende batteriniv\303\245 i menyen.",
"Skann etter bluetooth-enheter og opprett tilkobling.",
#ifdef _3DS
"Juster skriftskalaen for bunnskjerm.",
#endif
@@ -2629,7 +2631,7 @@ static const struct
* compiler that pads this struct fails here instead of
* misindexing at runtime. */
typedef char msg_hash_no_blob_check[
(sizeof(msg_hash_no_blob) == (29277u
(sizeof(msg_hash_no_blob) == (29330u
#ifdef HAVE_LAKKA
+ 178u
#endif
@@ -3683,6 +3685,7 @@ static const msg_hash_id_t msg_hash_no_ids[] =
(msg_hash_id_t)MENU_ENUM_SUBLABEL_AUDIO_RESPECT_SILENT_MODE,
(msg_hash_id_t)MENU_ENUM_SUBLABEL_AUDIO_SETTINGS,
(msg_hash_id_t)MENU_ENUM_SUBLABEL_BATTERY_LEVEL_ENABLE,
(msg_hash_id_t)MENU_ENUM_SUBLABEL_BLUETOOTH_SETTINGS,
#ifdef _3DS
(msg_hash_id_t)MENU_ENUM_SUBLABEL_BOTTOM_FONT_SCALE,
#endif
+4 -1
View File
@@ -2695,6 +2695,7 @@ static const struct
char s_aa08c6d6[71];
#endif
#endif
char s_27aef25c[59];
#ifdef _3DS
char s_2873cef1[75];
char s_b4816da6[53];
@@ -7521,6 +7522,7 @@ static const struct
"ze\305\204",
#endif
#endif
"Skanuj w poszukiwaniu urz\304\205dze\305\204 bluetooth i pod\305\202\304\205cz je.",
#ifdef _3DS
"Katalog zasob\303\263w dolnego ekranu. Katalog musi zawiera\304\207 \"bottom_menu.png\".",
"Dostosuj niebieski kolor czcionki na dolnym ekranie.",
@@ -10223,7 +10225,7 @@ static const struct
* compiler that pads this struct fails here instead of
* misindexing at runtime. */
typedef char msg_hash_pl_blob_check[
(sizeof(msg_hash_pl_blob) == (199656u
(sizeof(msg_hash_pl_blob) == (199715u
#ifdef ANDROID
+ 385u
#endif
@@ -13416,6 +13418,7 @@ static const msg_hash_id_t msg_hash_pl_ids[] =
(msg_hash_id_t)MENU_ENUM_SUBLABEL_BLUETOOTH_ERTM_DISABLE,
#endif
#endif
(msg_hash_id_t)MENU_ENUM_SUBLABEL_BLUETOOTH_SETTINGS,
#ifdef _3DS
(msg_hash_id_t)MENU_ENUM_SUBLABEL_BOTTOM_ASSETS_DIRECTORY,
(msg_hash_id_t)MENU_ENUM_SUBLABEL_BOTTOM_FONT_COLOR_BLUE,
+4 -1
View File
@@ -2566,6 +2566,7 @@ static const struct
char s_aa08c6d6[79];
#endif
#endif
char s_27aef25c[49];
#ifdef _3DS
char s_2873cef1[89];
char s_b4816da6[45];
@@ -7120,6 +7121,7 @@ static const struct
"Desativa o ERTM do Bluetooth para corrigir o pareamento de alguns dispositivos",
#endif
#endif
"Procura por dispositivos bluetooth e os conecta.",
#ifdef _3DS
"Diret\303\263rio dos recursos da tela inferior. O diret\303\263rio precisa ter um \"bottom_menu."
"png\".",
@@ -9526,7 +9528,7 @@ static const struct
* compiler that pads this struct fails here instead of
* misindexing at runtime. */
typedef char msg_hash_pt_br_blob_check[
(sizeof(msg_hash_pt_br_blob) == (193593u
(sizeof(msg_hash_pt_br_blob) == (193642u
#ifdef ANDROID
+ 352u
#endif
@@ -12550,6 +12552,7 @@ static const msg_hash_id_t msg_hash_pt_br_ids[] =
(msg_hash_id_t)MENU_ENUM_SUBLABEL_BLUETOOTH_ERTM_DISABLE,
#endif
#endif
(msg_hash_id_t)MENU_ENUM_SUBLABEL_BLUETOOTH_SETTINGS,
#ifdef _3DS
(msg_hash_id_t)MENU_ENUM_SUBLABEL_BOTTOM_ASSETS_DIRECTORY,
(msg_hash_id_t)MENU_ENUM_SUBLABEL_BOTTOM_FONT_COLOR_BLUE,
+6 -1
View File
@@ -2576,6 +2576,7 @@ static const struct
char s_aa08c6d6[133];
#endif
#endif
char s_27aef25c[67];
#ifdef _3DS
char s_2873cef1[119];
char s_b4816da6[83];
@@ -10864,6 +10865,9 @@ static const struct
"\203\321\201\321\202\321\200\320\276\320\271\321\201\321\202\320\262\320\260\321\205.",
#endif
#endif
"\320\237\320\276\320\270\321\201\320\272 \320\270 \320\277\320\276\320\264\320\272\320\273\321"
"\216\321\207\320\265\320\275\320\270\320\265 bluetooth-\321\203\321\201\321\202\321\200\320\276"
"\320\271\321\201\321\202\320\262.",
#ifdef _3DS
"\320\232\320\260\321\202\320\260\320\273\320\276\320\263 \321\200\320\265\321\201\321\203\321"
"\200\321\201\320\276\320\262 \320\264\320\273\321\217 \320\275\320\270\320\266\320\275\320\265"
@@ -19287,7 +19291,7 @@ static const struct
* compiler that pads this struct fails here instead of
* misindexing at runtime. */
typedef char msg_hash_ru_blob_check[
(sizeof(msg_hash_ru_blob) == (308285u
(sizeof(msg_hash_ru_blob) == (308352u
#ifdef ANDROID
+ 547u
#endif
@@ -22289,6 +22293,7 @@ static const msg_hash_id_t msg_hash_ru_ids[] =
(msg_hash_id_t)MENU_ENUM_SUBLABEL_BLUETOOTH_ERTM_DISABLE,
#endif
#endif
(msg_hash_id_t)MENU_ENUM_SUBLABEL_BLUETOOTH_SETTINGS,
#ifdef _3DS
(msg_hash_id_t)MENU_ENUM_SUBLABEL_BOTTOM_ASSETS_DIRECTORY,
(msg_hash_id_t)MENU_ENUM_SUBLABEL_BOTTOM_FONT_COLOR_BLUE,
+4 -492
View File
File diff suppressed because it is too large. Load diff
+4 -39
View File
@@ -2423,10 +2423,6 @@ static const struct
char s_bb929824[16];
char s_fe2ec9bd[33];
char s_1e3a9360[29];
char s_5943aeda[32];
char s_60b84450[35];
char s_782f95e3[33];
char s_5081d7d8[32];
char s_5741c1d0[14];
char s_a1a7717d[19];
char s_e6ca3876[32];
@@ -2832,6 +2828,7 @@ static const struct
char s_aa08c6d6[69];
#endif
#endif
char s_27aef25c[45];
#ifdef _3DS
char s_2873cef1[88];
char s_b4816da6[62];
@@ -4070,10 +4067,6 @@ static const struct
char s_72e21512[180];
char s_9f6de46b[288];
char s_26e66ece[211];
char s_5f131848[122];
char s_23227a3e[125];
char s_87e08991[123];
char s_56660806[122];
char s_66f2b57e[38];
char s_a776daeb[88];
char s_88095324[88];
@@ -4136,7 +4129,6 @@ static const struct
char s_dc6f9d69[55];
char s_417085f4[44];
char s_1bcf70a7[142];
char s_fbed99aa[170];
char s_2e2ca41a[296];
char s_f48b1fac[55];
char s_f4ad1b37[84];
@@ -4508,7 +4500,6 @@ static const struct
char s_e9eb2822[45];
char s_ed159cd6[16];
char s_fa458d88[36];
char s_f2f8ca3f[212];
char s_7ccec78e[41];
char s_308c47e4[40];
char s_525bf430[20];
@@ -7571,10 +7562,6 @@ static const struct
"Subpixel-layout",
"Anv\303\244nd bildsk\303\244rmens toppv\303\244rde",
"Maskinvaruavkodning av video",
"Undermarginal f\303\266r sk\303\244rmen (%)",
"V\303\244nstermarginal f\303\266r sk\303\244rmen (%)",
"H\303\266germarginal f\303\266r sk\303\244rmen (%)",
"\303\226vermarginal f\303\266r sk\303\244rmen (%)",
"Videolayouter",
"Max bildrutelatens",
"Maximalt antal swapchain-bilder",
@@ -8107,6 +8094,7 @@ static const struct
"Inaktivera Bluetooth ERTM f\303\266r att fixa parkoppling av vissa enheter",
#endif
#endif
"S\303\266k efter bluetooth-enheter och anslut dem.",
#ifdef _3DS
"Nedre sk\303\244rmens katalog f\303\266r tillg\303\245ngar. Katalogen m\303\245ste inkludera \"b"
"ottom_menu.png\".",
@@ -10235,14 +10223,6 @@ static const struct
"Avkoda videof\303\266rhandsvisningar p\303\245 GPU:n n\303\244r grafikdrivrutinen kan g\303\266r"
"a det (H.264 med Vulkan), s\303\245 att CPU:n avlastas. \342\200\235Av\342\200\235 avkodar dem p"
"\303\245 CPU:n. G\303\244ller f\303\266rhandsvisningar som \303\266ppnas fr\303\245n och med nu.",
"L\303\244mna utrymme vid nederkanten av spelet och menyn, i procent av f\303\266nstret, p\303"
"\245 iOS. 0 l\303\244gger inte till n\303\245gon marginal.",
"L\303\244mna utrymme vid v\303\244nsterkanten av spelet och menyn, i procent av f\303\266nstret,"
" p\303\245 iOS. 0 l\303\244gger inte till n\303\245gon marginal.",
"L\303\244mna utrymme vid h\303\266gerkanten av spelet och menyn, i procent av f\303\266nstret, p"
"\303\245 iOS. 0 l\303\244gger inte till n\303\245gon marginal.",
"L\303\244mna utrymme vid \303\266verkanten av spelet och menyn, i procent av f\303\266nstret, p"
"\303\245 iOS. 0 l\303\244gger inte till n\303\245gon marginal.",
"Videolayouter lagras i denna katalog.",
"S\303\244ger till videodrivrutinen att uttryckligen anv\303\244nda ett specificerat buffringsl"
"\303\244ge.",
@@ -10390,9 +10370,6 @@ static const struct
"V\303\244lj den flytande sk\303\244rm som ska justeras.",
"Kopplad beh\303\245ller sk\303\244rmen tillsammans med de andra. Separat visar den i ett eget f"
"\303\266nster eller p\303\245 en egen bildsk\303\244rm. Dold utel\303\244mnar den.",
"Var den h\303\244r sk\303\244rmen visas n\303\244r den har ett eget f\303\266nster. Auto v\303"
"\244ljer en annan bildsk\303\244rm. P\303\245 den bildsk\303\244rm d\303\244r RetroArch k\303"
"\266rs beh\303\245lls sk\303\244rmen i samma f\303\266nster.",
"St\303\244ng menyn och flytta VR-headsetets sk\303\244rmar och meny med handkontrollerna: greppk"
"nappen tar tag, avtryckaren vinklar, styrspaken \303\244ndrar avst\303\245nd och storlek, den fr"
"ia handens styrspak vrider och vinklar, huvudknappen \303\245terst\303\244ller och V\303\244lj n"
@@ -10933,9 +10910,6 @@ static const struct
"Filen finns redan. Sparar till reservbuffert",
"Filen hittas ej",
"En eller flera firmwarefiler saknas",
"Vissa av RetroArchs nedladdningsbara filer (menyresurser, handkontrollprofiler, k\303\244rninfor"
"mation, databaser) saknas.H\303\244mta dem nu? Det kr\303\244ver en internetanslutning.De kan up"
"pdateras senare med N\303\244tuppdateraren.",
"Mappspecifika k\303\244rnalternativ hittades i",
"Hittade automatiskt sparat tillst\303\245nd i",
"Hittade skivetikett",
@@ -11383,7 +11357,7 @@ static const struct
* compiler that pads this struct fails here instead of
* misindexing at runtime. */
typedef char msg_hash_sv_blob_check[
(sizeof(msg_hash_sv_blob) == (235556u
(sizeof(msg_hash_sv_blob) == (234595u
#ifdef ANDROID
+ 361u
#endif
@@ -14370,10 +14344,6 @@ static const msg_hash_id_t msg_hash_sv_ids[] =
(msg_hash_id_t)MENU_ENUM_LABEL_VALUE_VIDEO_HDR_SUBPIXEL_LAYOUT,
(msg_hash_id_t)MENU_ENUM_LABEL_VALUE_VIDEO_HDR_USE_DISPLAY_PEAK,
(msg_hash_id_t)MENU_ENUM_LABEL_VALUE_VIDEO_HW_DECODE,
(msg_hash_id_t)MENU_ENUM_LABEL_VALUE_VIDEO_IOS_MARGIN_BOTTOM,
(msg_hash_id_t)MENU_ENUM_LABEL_VALUE_VIDEO_IOS_MARGIN_LEFT,
(msg_hash_id_t)MENU_ENUM_LABEL_VALUE_VIDEO_IOS_MARGIN_RIGHT,
(msg_hash_id_t)MENU_ENUM_LABEL_VALUE_VIDEO_IOS_MARGIN_TOP,
(msg_hash_id_t)MENU_ENUM_LABEL_VALUE_VIDEO_LAYOUT_DIRECTORY,
(msg_hash_id_t)MENU_ENUM_LABEL_VALUE_VIDEO_MAX_FRAME_LATENCY,
(msg_hash_id_t)MENU_ENUM_LABEL_VALUE_VIDEO_MAX_SWAPCHAIN_IMAGES,
@@ -14772,6 +14742,7 @@ static const msg_hash_id_t msg_hash_sv_ids[] =
(msg_hash_id_t)MENU_ENUM_SUBLABEL_BLUETOOTH_ERTM_DISABLE,
#endif
#endif
(msg_hash_id_t)MENU_ENUM_SUBLABEL_BLUETOOTH_SETTINGS,
#ifdef _3DS
(msg_hash_id_t)MENU_ENUM_SUBLABEL_BOTTOM_ASSETS_DIRECTORY,
(msg_hash_id_t)MENU_ENUM_SUBLABEL_BOTTOM_FONT_COLOR_BLUE,
@@ -16008,10 +15979,6 @@ static const msg_hash_id_t msg_hash_sv_ids[] =
(msg_hash_id_t)MENU_ENUM_SUBLABEL_VIDEO_HDR_SUBPIXEL_LAYOUT,
(msg_hash_id_t)MENU_ENUM_SUBLABEL_VIDEO_HDR_USE_DISPLAY_PEAK,
(msg_hash_id_t)MENU_ENUM_SUBLABEL_VIDEO_HW_DECODE,
(msg_hash_id_t)MENU_ENUM_SUBLABEL_VIDEO_IOS_MARGIN_BOTTOM,
(msg_hash_id_t)MENU_ENUM_SUBLABEL_VIDEO_IOS_MARGIN_LEFT,
(msg_hash_id_t)MENU_ENUM_SUBLABEL_VIDEO_IOS_MARGIN_RIGHT,
(msg_hash_id_t)MENU_ENUM_SUBLABEL_VIDEO_IOS_MARGIN_TOP,
(msg_hash_id_t)MENU_ENUM_SUBLABEL_VIDEO_LAYOUT_DIRECTORY,
(msg_hash_id_t)MENU_ENUM_SUBLABEL_VIDEO_MAX_FRAME_LATENCY,
(msg_hash_id_t)MENU_ENUM_SUBLABEL_VIDEO_MAX_SWAPCHAIN_IMAGES,
@@ -16074,7 +16041,6 @@ static const msg_hash_id_t msg_hash_sv_ids[] =
(msg_hash_id_t)MENU_ENUM_SUBLABEL_VIDEO_SCREEN_LAYOUT,
(msg_hash_id_t)MENU_ENUM_SUBLABEL_VIDEO_SCREEN_SELECTED,
(msg_hash_id_t)MENU_ENUM_SUBLABEL_VIDEO_SCREEN_WINDOW_MODE,
(msg_hash_id_t)MENU_ENUM_SUBLABEL_VIDEO_SCREEN_WINDOW_MONITOR,
(msg_hash_id_t)MENU_ENUM_SUBLABEL_VIDEO_SCREEN_XR_EDIT,
(msg_hash_id_t)MENU_ENUM_SUBLABEL_VIDEO_SCREEN_XR_PITCH,
(msg_hash_id_t)MENU_ENUM_SUBLABEL_VIDEO_SCREEN_XR_RESET,
@@ -16441,7 +16407,6 @@ static const msg_hash_id_t msg_hash_sv_ids[] =
(msg_hash_id_t)MSG_FILE_ALREADY_EXISTS_SAVING_TO_BACKUP_BUFFER,
(msg_hash_id_t)MSG_FILE_NOT_FOUND,
(msg_hash_id_t)MSG_FIRMWARE,
(msg_hash_id_t)MSG_FIRST_RUN_DOWNLOAD_PROMPT,
(msg_hash_id_t)MSG_FOLDER_SPECIFIC_CORE_OPTIONS_FOUND_AT,
(msg_hash_id_t)MSG_FOUND_AUTO_SAVESTATE_IN,
(msg_hash_id_t)MSG_FOUND_DISK_LABEL,
+7 -1
View File
@@ -2605,6 +2605,7 @@ static const struct
char s_aa08c6d6[164];
#endif
#endif
char s_27aef25c[94];
#ifdef _3DS
char s_2873cef1[209];
char s_b4816da6[124];
@@ -13114,6 +13115,10 @@ static const struct
"\243\340\270\223\340\271\214",
#endif
#endif
"\340\270\252\340\271\201\340\270\201\340\270\231\340\270\253\340\270\262\340\270\255\340\270\270"
"\340\270\233\340\270\201\340\270\243\340\270\223\340\271\214\340\270\232\340\270\245\340\270\271"
"\340\270\227\340\270\271\340\270\230\340\271\201\340\270\245\340\270\260\340\271\200\340\270\212"
"\340\270\267\340\271\210\340\270\255\340\270\241\340\270\225\340\271\210\340\270\255",
#ifdef _3DS
"\340\271\204\340\270\224\340\271\200\340\270\243\340\270\201\340\270\227\340\270\255\340\270\243"
"\340\270\265\340\270\227\340\270\243\340\270\261\340\270\236\340\270\242\340\270\262\340\270\201"
@@ -26511,7 +26516,7 @@ static const struct
* compiler that pads this struct fails here instead of
* misindexing at runtime. */
typedef char msg_hash_th_blob_check[
(sizeof(msg_hash_th_blob) == (453615u
(sizeof(msg_hash_th_blob) == (453709u
#ifdef ANDROID
+ 757u
#endif
@@ -29611,6 +29616,7 @@ static const msg_hash_id_t msg_hash_th_ids[] =
(msg_hash_id_t)MENU_ENUM_SUBLABEL_BLUETOOTH_ERTM_DISABLE,
#endif
#endif
(msg_hash_id_t)MENU_ENUM_SUBLABEL_BLUETOOTH_SETTINGS,
#ifdef _3DS
(msg_hash_id_t)MENU_ENUM_SUBLABEL_BOTTOM_ASSETS_DIRECTORY,
(msg_hash_id_t)MENU_ENUM_SUBLABEL_BOTTOM_FONT_COLOR_BLUE,
+4 -1
View File
@@ -2369,6 +2369,7 @@ static const struct
char s_aa08c6d6[76];
#endif
#endif
char s_27aef25c[56];
#ifdef _3DS
char s_2873cef1[64];
char s_b4816da6[46];
@@ -6689,6 +6690,7 @@ static const struct
"\237\304\261 b\304\261rak\304\261n",
#endif
#endif
"Bluetooth cihazlar\304\261n\304\261 tarar ve ba\304\237lant\304\261 olu\305\237turur.",
#ifdef _3DS
"Alt ekran i\303\247erik dizini. Dizin 'bottom_menu.png' i\303\247ermelidir.",
"Alt ekran yaz\304\261 tipi mavi rengini ayarlay\304\261n.",
@@ -9193,7 +9195,7 @@ static const struct
* compiler that pads this struct fails here instead of
* misindexing at runtime. */
typedef char msg_hash_tr_blob_check[
(sizeof(msg_hash_tr_blob) == (169266u
(sizeof(msg_hash_tr_blob) == (169322u
#ifdef ANDROID
+ 340u
#endif
@@ -11922,6 +11924,7 @@ static const msg_hash_id_t msg_hash_tr_ids[] =
(msg_hash_id_t)MENU_ENUM_SUBLABEL_BLUETOOTH_ERTM_DISABLE,
#endif
#endif
(msg_hash_id_t)MENU_ENUM_SUBLABEL_BLUETOOTH_SETTINGS,
#ifdef _3DS
(msg_hash_id_t)MENU_ENUM_SUBLABEL_BOTTOM_ASSETS_DIRECTORY,
(msg_hash_id_t)MENU_ENUM_SUBLABEL_BOTTOM_FONT_COLOR_BLUE,
+7 -1
View File
@@ -2755,6 +2755,7 @@ static const struct
char s_aa08c6d6[103];
#endif
#endif
char s_27aef25c[86];
#ifdef _3DS
char s_2873cef1[127];
char s_b4816da6[79];
@@ -11992,6 +11993,10 @@ static const struct
"\321\200\320\270\321\201\321\202\321\200\320\276\321\227\320\262",
#endif
#endif
"\320\241\320\272\320\260\320\275\321\203\320\262\320\260\321\202\320\270 \320\264\320\273\321"
"\217 Bluetooth \320\277\321\200\320\270\321\201\321\202\321\200\320\276\321\227\320\262 \321\202"
"\320\260 \320\277\321\226\320\264'\321\224\320\264\320\275\320\260\321\202\320\270 \321\227\321"
"\205.",
#ifdef _3DS
"\320\235\320\270\320\266\320\275\321\226\320\271 \320\265\320\272\321\200\320\260\320\275\320"
"\275\320\270\320\271 \320\272\320\260\321\202\320\260\320\273\320\276\320\263 \320\260\320\272"
@@ -21392,7 +21397,7 @@ static const struct
* compiler that pads this struct fails here instead of
* misindexing at runtime. */
typedef char msg_hash_uk_blob_check[
(sizeof(msg_hash_uk_blob) == (349349u
(sizeof(msg_hash_uk_blob) == (349435u
#ifdef ANDROID
+ 610u
#endif
@@ -24562,6 +24567,7 @@ static const msg_hash_id_t msg_hash_uk_ids[] =
(msg_hash_id_t)MENU_ENUM_SUBLABEL_BLUETOOTH_ERTM_DISABLE,
#endif
#endif
(msg_hash_id_t)MENU_ENUM_SUBLABEL_BLUETOOTH_SETTINGS,
#ifdef _3DS
(msg_hash_id_t)MENU_ENUM_SUBLABEL_BOTTOM_ASSETS_DIRECTORY,
(msg_hash_id_t)MENU_ENUM_SUBLABEL_BOTTOM_FONT_COLOR_BLUE,
+5 -1
View File
@@ -3007,6 +3007,7 @@ static const struct
char s_aa08c6d6[90];
#endif
#endif
char s_27aef25c[51];
#ifdef _3DS
char s_2873cef1[91];
char s_b4816da6[73];
@@ -9569,6 +9570,8 @@ static const struct
" b\341\273\213",
#endif
#endif
"Qu\303\251t c\303\241c thi\341\272\277t b\341\273\213 Bluetooth v\303\240 k\341\272\277t n\341"
"\273\221i.",
#ifdef _3DS
"Th\306\260 m\341\273\245c t\303\240i nguy\303\252n m\303\240n h\303\254nh d\306\260\341\273\233i"
". Th\306\260 m\341\273\245c ph\341\272\243i bao g\341\273\223m \"bottom_menu.png\".",
@@ -15669,7 +15672,7 @@ static const struct
* compiler that pads this struct fails here instead of
* misindexing at runtime. */
typedef char msg_hash_vn_blob_check[
(sizeof(msg_hash_vn_blob) == (312801u
(sizeof(msg_hash_vn_blob) == (312852u
#ifdef ANDROID
+ 373u
#endif
@@ -19225,6 +19228,7 @@ static const msg_hash_id_t msg_hash_vn_ids[] =
(msg_hash_id_t)MENU_ENUM_SUBLABEL_BLUETOOTH_ERTM_DISABLE,
#endif
#endif
(msg_hash_id_t)MENU_ENUM_SUBLABEL_BLUETOOTH_SETTINGS,
#ifdef _3DS
(msg_hash_id_t)MENU_ENUM_SUBLABEL_BOTTOM_ASSETS_DIRECTORY,
(msg_hash_id_t)MENU_ENUM_SUBLABEL_BOTTOM_FONT_COLOR_BLUE,
+2 -2
View File
@@ -127,7 +127,7 @@
#define LANGUAGE_PROGRESS_RUSSIAN_APPROVED 5
/* Slovak */
#define LANGUAGE_PROGRESS_SLOVAK_TRANSLATED 99
#define LANGUAGE_PROGRESS_SLOVAK_TRANSLATED 95
#define LANGUAGE_PROGRESS_SLOVAK_APPROVED 0
/* Serbian (Latin) */
@@ -159,7 +159,7 @@
#define LANGUAGE_PROGRESS_VALENCIAN_APPROVED 0
/* Vietnamese */
#define LANGUAGE_PROGRESS_VIETNAMESE_TRANSLATED 99
#define LANGUAGE_PROGRESS_VIETNAMESE_TRANSLATED 100
#define LANGUAGE_PROGRESS_VIETNAMESE_APPROVED 0
/* Chinese Simplified */
+107 -10
View File
@@ -387,11 +387,47 @@ static INLINE float audio_mixer_bits_float(int i)
#ifdef AUDIO_MIXER_HAS_STREAM
/* ---- folding a multichannel stream to the stereo a voice mixes ------
*
* A voice mixes stereo, so anything wider is folded here - the arms
* deliberately do no channel conversion. The fold for each arm's
* channel order is audio_transfer's (audio_transfer_fold_q15): Vorbis
* and Opus in Vorbis order, the rest in WAVE order, WMA by its speaker
* mask. Q15 in int32; the s16 fold stays clear of float. */
* Vorbis and Opus both decode more than two channels now, and so do
* WAV and FLAC - but they do not agree on what order the channels
* arrive in, so there are two tables and the caller says which.
*
* Vorbis's order (spec 4.3.9), which Opus mapping family 1 adopts:
*
* 3 L C R 4 L R RL RR 5 L C R RL RR
* 6 L C R RL RR LFE 7 L C R RL RR BC LFE
* 8 L C R RL RR SL SR LFE
*
* Microsoft's, which WAV carries and FLAC's spec matches:
*
* 3 FL FR FC 4 FL FR BL BR 5 FL FR FC BL BR
* 6 FL FR FC LFE BL BR 7 FL FR FC LFE BC SL SR
* 8 FL FR FC LFE BL BR SL SR
*
* Folding one with the other's table is not a subtle error: on 5.1 it
* sends front-right to both sides, front-centre to the right alone,
* LFE into the mix and back-right nowhere.
*
* A stream voice mixes stereo, so anything wider is folded here - the
* arms deliberately do no channel conversion, leaving it to the
* mixer. Coefficients are the usual ITU-R BS.775 ones: centre and
* surrounds enter both sides at -3 dB, a lone back centre at -6 dB
* into each, and LFE is dropped, which is what it is for.
*
* Not normalised. Scaling by the coefficient sum would put 5.1
* content 7.7 dB below the same material in a stereo file, which is a
* surprising thing for a file's channel count to do to its volume;
* the sum only reaches full scale when the channels are correlated,
* and the mixer already clamps at its s16 and float boundaries. The
* trade is level for the possibility of clipping on correlated
* material, and it is the trade most players make.
*
* Q15 in int32 - unity is 32768, which does not fit the int16 the
* coefficients would otherwise want, and wrapping it would invert a
* channel rather than pass it. The s16 fold stays clear of float. */
#define AMIX_DM_UNITY 32768
#define AMIX_DM_M3DB 23170
#define AMIX_DM_M6DB 16384
static int16_t audio_mixer_sat_s16_64(int64_t v)
{
if (v > 32767)
@@ -401,6 +437,59 @@ static int16_t audio_mixer_sat_s16_64(int64_t v)
return (int16_t)v;
}
/* [channels][input channel][0 = left, 1 = right] */
static const int32_t audio_mixer_downmix_vorbis_q15[9][8][2] = {
{ {0,0} }, /* unused */
{ {0,0} }, /* mono */
{ {0,0} }, /* stereo */
/* 3: L C R */
{ {AMIX_DM_UNITY,0}, {AMIX_DM_M3DB,AMIX_DM_M3DB}, {0,AMIX_DM_UNITY} },
/* 4: L R RL RR */
{ {AMIX_DM_UNITY,0}, {0,AMIX_DM_UNITY},
{AMIX_DM_M3DB,0}, {0,AMIX_DM_M3DB} },
/* 5: L C R RL RR */
{ {AMIX_DM_UNITY,0}, {AMIX_DM_M3DB,AMIX_DM_M3DB}, {0,AMIX_DM_UNITY},
{AMIX_DM_M3DB,0}, {0,AMIX_DM_M3DB} },
/* 6: L C R RL RR LFE */
{ {AMIX_DM_UNITY,0}, {AMIX_DM_M3DB,AMIX_DM_M3DB}, {0,AMIX_DM_UNITY},
{AMIX_DM_M3DB,0}, {0,AMIX_DM_M3DB}, {0,0} },
/* 7: L C R RL RR BC LFE */
{ {AMIX_DM_UNITY,0}, {AMIX_DM_M3DB,AMIX_DM_M3DB}, {0,AMIX_DM_UNITY},
{AMIX_DM_M3DB,0}, {0,AMIX_DM_M3DB},
{AMIX_DM_M6DB,AMIX_DM_M6DB}, {0,0} },
/* 8: L C R RL RR SL SR LFE */
{ {AMIX_DM_UNITY,0}, {AMIX_DM_M3DB,AMIX_DM_M3DB}, {0,AMIX_DM_UNITY},
{AMIX_DM_M3DB,0}, {0,AMIX_DM_M3DB},
{AMIX_DM_M3DB,0}, {0,AMIX_DM_M3DB}, {0,0} }
};
/* Microsoft/FLAC order. */
static const int32_t audio_mixer_downmix_wav_q15[9][8][2] = {
{ {0,0} }, /* unused */
{ {0,0} }, /* mono */
{ {0,0} }, /* stereo */
/* 3: FL FR FC */
{ {AMIX_DM_UNITY,0}, {0,AMIX_DM_UNITY}, {AMIX_DM_M3DB,AMIX_DM_M3DB} },
/* 4: FL FR BL BR */
{ {AMIX_DM_UNITY,0}, {0,AMIX_DM_UNITY},
{AMIX_DM_M3DB,0}, {0,AMIX_DM_M3DB} },
/* 5: FL FR FC BL BR */
{ {AMIX_DM_UNITY,0}, {0,AMIX_DM_UNITY}, {AMIX_DM_M3DB,AMIX_DM_M3DB},
{AMIX_DM_M3DB,0}, {0,AMIX_DM_M3DB} },
/* 6: FL FR FC LFE BL BR */
{ {AMIX_DM_UNITY,0}, {0,AMIX_DM_UNITY}, {AMIX_DM_M3DB,AMIX_DM_M3DB},
{0,0}, {AMIX_DM_M3DB,0}, {0,AMIX_DM_M3DB} },
/* 7: FL FR FC LFE BC SL SR */
{ {AMIX_DM_UNITY,0}, {0,AMIX_DM_UNITY}, {AMIX_DM_M3DB,AMIX_DM_M3DB},
{0,0}, {AMIX_DM_M6DB,AMIX_DM_M6DB},
{AMIX_DM_M3DB,0}, {0,AMIX_DM_M3DB} },
/* 8: FL FR FC LFE BL BR SL SR */
{ {AMIX_DM_UNITY,0}, {0,AMIX_DM_UNITY}, {AMIX_DM_M3DB,AMIX_DM_M3DB},
{0,0}, {AMIX_DM_M3DB,0}, {0,AMIX_DM_M3DB},
{AMIX_DM_M3DB,0}, {0,AMIX_DM_M3DB} }
};
/* Which order an arm hands its channels over in. */
static const int32_t (*audio_mixer_downmix_table(
enum audio_type_enum type, unsigned ch, const audio_mixer_voice_t *voice))[2]
@@ -409,7 +498,15 @@ static const int32_t (*audio_mixer_downmix_table(
#ifdef HAVE_RWMA
if (type == AUDIO_TYPE_WMA) return voice->types.stream.wma_matrix;
#endif
return audio_transfer_fold_q15(type, ch);
switch (type)
{
case AUDIO_TYPE_VORBIS:
case AUDIO_TYPE_OPUS:
return audio_mixer_downmix_vorbis_q15[ch];
default:
break;
}
return audio_mixer_downmix_wav_q15[ch];
}
/* Frames a temp buffer of 'samples' holds at 'ch' channels: what a
@@ -499,7 +596,7 @@ static float wav_sample_unit(const rwav_t *wav, const uint8_t *src,
static void wav_fold_to_stereo(const rwav_t *wav, const uint8_t *src,
float *dst, size_t frames)
{
const int32_t (*co)[2] = audio_transfer_fold_q15(AUDIO_TYPE_WAV, wav->numchannels);
const int32_t (*co)[2] = audio_mixer_downmix_wav_q15[wav->numchannels];
size_t i;
for (i = 0; i < frames; i++)
{
@@ -577,7 +674,7 @@ static bool wav_to_float(const rwav_t* wav, const uint8_t* src,
got = rwav_decode_s16(&h, src, 0, wav->numsamples, tmp);
{
const int32_t (*co)[2] =
audio_transfer_fold_q15(AUDIO_TYPE_WAV, wav->numchannels);
audio_mixer_downmix_wav_q15[wav->numchannels];
unsigned c;
for (i = 0; i < got; i++)
{
@@ -920,7 +1017,7 @@ static bool wav_to_s16(const rwav_t* wav, const uint8_t* src,
got = rwav_decode_s16(&h, src, 0, wav->numsamples, tmp);
{
const int32_t (*co)[2] =
audio_transfer_fold_q15(AUDIO_TYPE_WAV, wav->numchannels);
audio_mixer_downmix_wav_q15[wav->numchannels];
unsigned c;
for (i = 0; i < got; i++)
{
@@ -949,7 +1046,7 @@ static bool wav_to_s16(const rwav_t* wav, const uint8_t* src,
size_t i2;
unsigned c;
const int32_t (*co)[2] =
audio_transfer_fold_q15(AUDIO_TYPE_WAV, wav->numchannels);
audio_mixer_downmix_wav_q15[wav->numchannels];
for (i2 = 0; i2 < wav->numsamples; i2++)
{
int64_t l = 0, r = 0;
@@ -1,83 +0,0 @@
/* Copyright (C) 2010-2026 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (float_to_ulaw.c).
* ---------------------------------------------------------------------------------------
*
* Permission is hereby granted, free of charge,
* to any person obtaining a copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/* G.711 mu-law: see audio/conversion/float_to_ulaw.h. */
#include <audio/conversion/float_to_ulaw.h>
/* The level code @i (0..127, magnitude) decodes to, 16-bit scale */
static int ulaw_level(int i)
{
return ((((i & 15) << 3) + 0x84) << (i >> 4)) - 0x84;
}
/* The code for magnitude @j (1..8192, 14-bit scale): the first whose
* decision level - halfway to the next code's level, rounded - is above
* it, or 127 past the last; seven steps of a binary search */
static int ulaw_code(int j)
{
int lo = 0, hi = 127;
while (lo < hi)
{
int mid = (lo + hi) >> 1;
if (j < ((ulaw_level(mid) + ulaw_level(mid + 1) + 4) >> 3))
hi = mid;
else
lo = mid + 1;
}
return lo;
}
static uint8_t ulaw_from_s16(int s)
{
int idx = (s + 32768) >> 2; /* 0..16383, 8192 at zero */
if (idx > 8192)
return (uint8_t)(ulaw_code(idx - 8192) ^ 0xFF);
if (idx == 8192)
return 0xFF;
return (uint8_t)(ulaw_code(8192 - idx) ^ 0x7F);
}
void convert_s16_to_ulaw(uint8_t *out, const int16_t *in, size_t samples)
{
size_t i;
for (i = 0; i < samples; i++)
out[i] = ulaw_from_s16(in[i]);
}
void convert_float_to_ulaw(uint8_t *out, const float *in, size_t samples)
{
size_t i;
for (i = 0; i < samples; i++)
{
float f = in[i] * 32768.0f;
int s;
/* clipped, then rounded half away from zero */
if (f >= 32767.0f)
s = 32767;
else if (f <= -32768.0f)
s = -32768;
else
s = (int)(f < 0 ? f - 0.5f : f + 0.5f);
out[i] = ulaw_from_s16(s);
}
}
-278
View File
@@ -574,117 +574,6 @@ static void aes_x86_cbc_decrypt(const struct aes_ctx *ctx, uint8_t *iv,
_mm_storeu_si128((__m128i*)iv, prev);
}
/* XTS (IEEE 1619): the tweak is multiplied by alpha from one block to
* the next. As a little-endian 128-bit number it is a shift left by
* one, the bit out of the low half carried into the high one and the
* one out of the top folded back in as 0x87. */
AES_TARGET_X86
static __m128i aes_x86_xts_next(__m128i t)
{
/* lane 0: the top bit, lane 1: the low half's top bit; times 0x87
* and 1, which the carries being 0 or 1 make a multiply */
const __m128i poly = _mm_set_epi32(0, 1, 0, 0x87);
const __m128i carry = _mm_shuffle_epi32(_mm_srli_epi64(t, 63), 0x4e);
return _mm_xor_si128(_mm_slli_epi64(t, 1), _mm_mul_epu32(carry, poly));
}
/* XTS over whole blocks, eight in flight, from the encrypted tweak
* @tweak; the round keys made once per call (through InvMixColumns to
* decrypt). Each block's input is held in a register before its output
* is stored, so @in and @out may alias. The tweak comes as bytes: a
* vector argument would be loaded by the caller, which is built
* without SSE on i686. */
AES_TARGET_X86
static void aes_x86_xts(const struct aes_ctx *ctx, const uint8_t *tweak,
const uint8_t *in, uint8_t *out, size_t len, int decrypt)
{
__m128i k[15];
__m128i t = _mm_loadu_si128((const __m128i*)tweak);
unsigned r, nr = ctx->rounds;
if (decrypt)
{
k[0] = aes_x86_bswap32(_mm_loadu_si128((const __m128i*)(ctx->rk + 4 * nr)));
k[nr] = aes_x86_bswap32(_mm_loadu_si128((const __m128i*)ctx->rk));
for (r = 1; r < nr; r++)
k[r] = _mm_aesimc_si128(aes_x86_bswap32(
_mm_loadu_si128((const __m128i*)(ctx->rk + 4 * (nr - r)))));
}
else
for (r = 0; r <= nr; r++)
k[r] = aes_x86_bswap32(_mm_loadu_si128((const __m128i*)(ctx->rk + 4 * r)));
#define AES_X86_XTS_ROUNDS(op, oplast) \
for (r = 1; r < nr; r++) \
{ \
const __m128i kr = k[r]; \
b0 = op(b0, kr); b1 = op(b1, kr); b2 = op(b2, kr); b3 = op(b3, kr); \
b4 = op(b4, kr); b5 = op(b5, kr); b6 = op(b6, kr); b7 = op(b7, kr); \
} \
b0 = oplast(b0, k[nr]); b1 = oplast(b1, k[nr]); \
b2 = oplast(b2, k[nr]); b3 = oplast(b3, k[nr]); \
b4 = oplast(b4, k[nr]); b5 = oplast(b5, k[nr]); \
b6 = oplast(b6, k[nr]); b7 = oplast(b7, k[nr]);
while (len >= 128)
{
const __m128i t0 = t;
const __m128i t1 = aes_x86_xts_next(t0);
const __m128i t2 = aes_x86_xts_next(t1);
const __m128i t3 = aes_x86_xts_next(t2);
const __m128i t4 = aes_x86_xts_next(t3);
const __m128i t5 = aes_x86_xts_next(t4);
const __m128i t6 = aes_x86_xts_next(t5);
const __m128i t7 = aes_x86_xts_next(t6);
__m128i b0 = _mm_xor_si128(_mm_xor_si128(_mm_loadu_si128((const __m128i*)(in)), t0), k[0]);
__m128i b1 = _mm_xor_si128(_mm_xor_si128(_mm_loadu_si128((const __m128i*)(in + 16)), t1), k[0]);
__m128i b2 = _mm_xor_si128(_mm_xor_si128(_mm_loadu_si128((const __m128i*)(in + 32)), t2), k[0]);
__m128i b3 = _mm_xor_si128(_mm_xor_si128(_mm_loadu_si128((const __m128i*)(in + 48)), t3), k[0]);
__m128i b4 = _mm_xor_si128(_mm_xor_si128(_mm_loadu_si128((const __m128i*)(in + 64)), t4), k[0]);
__m128i b5 = _mm_xor_si128(_mm_xor_si128(_mm_loadu_si128((const __m128i*)(in + 80)), t5), k[0]);
__m128i b6 = _mm_xor_si128(_mm_xor_si128(_mm_loadu_si128((const __m128i*)(in + 96)), t6), k[0]);
__m128i b7 = _mm_xor_si128(_mm_xor_si128(_mm_loadu_si128((const __m128i*)(in + 112)), t7), k[0]);
if (decrypt)
{
AES_X86_XTS_ROUNDS(_mm_aesdec_si128, _mm_aesdeclast_si128)
}
else
{
AES_X86_XTS_ROUNDS(_mm_aesenc_si128, _mm_aesenclast_si128)
}
_mm_storeu_si128((__m128i*)(out), _mm_xor_si128(b0, t0));
_mm_storeu_si128((__m128i*)(out + 16), _mm_xor_si128(b1, t1));
_mm_storeu_si128((__m128i*)(out + 32), _mm_xor_si128(b2, t2));
_mm_storeu_si128((__m128i*)(out + 48), _mm_xor_si128(b3, t3));
_mm_storeu_si128((__m128i*)(out + 64), _mm_xor_si128(b4, t4));
_mm_storeu_si128((__m128i*)(out + 80), _mm_xor_si128(b5, t5));
_mm_storeu_si128((__m128i*)(out + 96), _mm_xor_si128(b6, t6));
_mm_storeu_si128((__m128i*)(out + 112), _mm_xor_si128(b7, t7));
t = aes_x86_xts_next(t7);
in += 128;
out += 128;
len -= 128;
}
#undef AES_X86_XTS_ROUNDS
for (; len >= 16; in += 16, out += 16, len -= 16)
{
__m128i b = _mm_xor_si128(_mm_xor_si128(_mm_loadu_si128((const __m128i*)in), t), k[0]);
if (decrypt)
{
for (r = 1; r < nr; r++)
b = _mm_aesdec_si128(b, k[r]);
b = _mm_aesdeclast_si128(b, k[nr]);
}
else
{
for (r = 1; r < nr; r++)
b = _mm_aesenc_si128(b, k[r]);
b = _mm_aesenclast_si128(b, k[nr]);
}
_mm_storeu_si128((__m128i*)out, _mm_xor_si128(b, t));
t = aes_x86_xts_next(t);
}
}
/* CTR with eight blocks in flight so the AES unit's latency is hidden,
* the round keys loaded and byte-swapped once per call rather than once
* per round. The counter block is kept byte-reversed, where its 32-bit
@@ -1078,73 +967,6 @@ static void aes_arm_cbc_decrypt(const struct aes_ctx *ctx, uint8_t *iv,
vst1q_u8(iv, prev);
}
/* XTS's tweak times alpha, as the x86 form above: each half shifted
* left, the carries exchanged and the top one folded in as 0x87. */
AES_TARGET_ARM
static uint8x16_t aes_arm_xts_next(uint8x16_t t)
{
static const uint64_t poly_v[2] = { 0x87, 1 };
const uint64x2_t v = vreinterpretq_u64_u8(t);
const uint64x2_t top = vshrq_n_u64(v, 63);
const uint64x2_t carry = vextq_u64(top, top, 1);
const uint64x2_t mask = vsubq_u64(vdupq_n_u64(0), carry);
return vreinterpretq_u8_u64(veorq_u64(vshlq_n_u64(v, 1),
vandq_u64(mask, vld1q_u64(poly_v))));
}
/* XTS over whole blocks, eight in flight, the round keys loaded once.
* Decrypting is the CBC decryption's AESD chain, encrypting the CTR's
* AESE chain; the tweak goes in before the first round key and out
* after the last. */
AES_TARGET_ARM
static void aes_arm_xts(const struct aes_ctx *ctx, uint8x16_t t,
const uint8_t *in, uint8_t *out, size_t len, int decrypt)
{
uint8x16_t k[15];
unsigned r, nr = ctx->rounds;
for (r = 0; r <= nr; r++)
k[r] = aes_arm_rk(ctx, r);
if (decrypt)
for (r = 1; r < nr; r++)
k[r] = vaesimcq_u8(k[r]);
while (len >= 16)
{
uint8x16_t tw[8], b[8];
unsigned i, n = len >= 128 ? 8 : 1;
for (i = 0; i < n; i++)
{
tw[i] = t;
b[i] = veorq_u8(vld1q_u8(in + 16 * i), t);
t = aes_arm_xts_next(t);
}
if (decrypt)
{
for (i = 0; i < n; i++)
b[i] = vaesdq_u8(b[i], k[nr]);
for (r = nr - 1; r > 0; r--)
for (i = 0; i < n; i++)
b[i] = vaesdq_u8(vaesimcq_u8(b[i]), k[r]);
for (i = 0; i < n; i++)
b[i] = veorq_u8(b[i], k[0]);
}
else
{
for (r = 0; r + 1 < nr; r++)
for (i = 0; i < n; i++)
b[i] = vaesmcq_u8(vaeseq_u8(b[i], k[r]));
for (i = 0; i < n; i++)
b[i] = veorq_u8(vaeseq_u8(b[i], k[nr - 1]), k[nr]);
}
for (i = 0; i < n; i++)
vst1q_u8(out + 16 * i, veorq_u8(b[i], tw[i]));
in += 16 * n;
out += 16 * n;
len -= 16 * n;
}
}
/* CTR with eight blocks in flight, the round keys loaded once per
* call. The counter block is kept byte-reversed within each 32-bit
* lane, where its big-endian counter is lane 3 as a native word: one
@@ -1619,42 +1441,6 @@ void aes_ctr_crypt(const struct aes_ctx *ctx, uint8_t *counter,
crypto_memzero(ks, sizeof(ks));
}
/* The register holds ciphertext: encrypting it gives the next
* keystream block, and each ciphertext octet goes back into it. */
void aes_cfb128_encrypt(const struct aes_ctx *ctx, uint8_t *iv,
unsigned *num, const uint8_t *in, uint8_t *out, size_t len)
{
unsigned n = *num & 15;
while (len)
{
if (!n)
aes_encrypt_block(ctx, iv, iv);
iv[n] ^= *in++;
*out++ = iv[n];
n = (n + 1) & 15;
len--;
}
*num = n;
}
void aes_cfb128_decrypt(const struct aes_ctx *ctx, uint8_t *iv,
unsigned *num, const uint8_t *in, uint8_t *out, size_t len)
{
unsigned n = *num & 15;
while (len)
{
uint8_t c;
if (!n)
aes_encrypt_block(ctx, iv, iv);
c = *in++;
*out++ = (uint8_t)(iv[n] ^ c);
iv[n] = c;
n = (n + 1) & 15;
len--;
}
*num = n;
}
void aes_cbc_encrypt(const struct aes_ctx *ctx, uint8_t *iv,
const uint8_t *in, uint8_t *out, size_t len)
{
@@ -1729,70 +1515,6 @@ void aes_cbc_decrypt(const struct aes_ctx *ctx, uint8_t *iv,
memcpy(iv, prev, 16);
}
/* The tweak times alpha in GF(2^128), as a little-endian number: a
* shift left, the bit out of the top folded back in as 0x87. */
static void aes_xts_next(uint8_t *t)
{
unsigned i;
uint8_t carry = 0;
for (i = 0; i < 16; i++)
{
uint8_t next = t[i] >> 7;
t[i] = (uint8_t)((t[i] << 1) | carry);
carry = next;
}
t[0] ^= (uint8_t)(0x87 & (0 - carry));
}
static void aes_xts(const struct aes_ctx *data_key,
const struct aes_ctx *tweak_key, const uint8_t *tweak,
const uint8_t *in, uint8_t *out, size_t len, int decrypt)
{
uint8_t t[16], b[16], o[16];
unsigned i;
aes_encrypt_block(tweak_key, tweak, t);
#if defined(AES_HAVE_X86_PATH)
if (aes_x86_available())
{
aes_x86_xts(data_key, t, in, out, len, decrypt);
return;
}
#elif defined(AES_HAVE_ARM_PATH)
if (aes_arm_available())
{
aes_arm_xts(data_key, vld1q_u8(t), in, out, len, decrypt);
return;
}
#endif
for (; len >= 16; in += 16, out += 16, len -= 16)
{
for (i = 0; i < 16; i++)
b[i] = in[i] ^ t[i];
if (decrypt)
aes_decrypt_block_c(data_key, b, o);
else
aes_encrypt_block_c(data_key, b, o);
for (i = 0; i < 16; i++)
out[i] = o[i] ^ t[i];
aes_xts_next(t);
}
}
void aes_xts_encrypt(const struct aes_ctx *data_key,
const struct aes_ctx *tweak_key, const uint8_t *tweak,
const uint8_t *in, uint8_t *out, size_t len)
{
aes_xts(data_key, tweak_key, tweak, in, out, len, 0);
}
void aes_xts_decrypt(const struct aes_ctx *data_key,
const struct aes_ctx *tweak_key, const uint8_t *tweak,
const uint8_t *in, uint8_t *out, size_t len)
{
aes_xts(data_key, tweak_key, tweak, in, out, len, 1);
}
/* Double in GF(2^128) with the CMAC polynomial. */
static void aes_cmac_dbl(uint8_t *b)
{
+2 -45
View File
@@ -407,11 +407,6 @@ static uint32_t rd_adler32_update(uint32_t adler,
return rd_adler32_on(adler, buf, len, 16);
}
uint32_t encoding_adler32(uint32_t adler, const uint8_t *buf, size_t len)
{
return rd_adler32_update(adler, buf, len);
}
/* Test entry point for tools/encodings/adler32_test.c: the kernel above is
* static, and driving it only through rinflate/rdeflate would exercise
* whatever lengths and alignments a stream happens to produce rather than
@@ -2225,7 +2220,6 @@ struct rdeflate
uint32_t crc; /* gzip: running crc32 of the input */
uint32_t total_in; /* gzip: mod 2^32, for ISIZE */
int final_in; /* caller signalled end of input */
int flush_req; /* sync flush asked for: 1 pending, 2 marker out */
int done;
int error;
@@ -2950,14 +2944,6 @@ void rdeflate_finish(void *data)
s->final_in = 1;
}
/* write out everything taken so far, ending on a byte boundary */
void rdeflate_flush(void *data)
{
struct rdeflate *s = (struct rdeflate*)data;
if (!s->flush_req)
s->flush_req = 1;
}
/* ------- the parser: consume win[block_start..win_len) into symbols ------- */
/* Fills the symbol buffer using greedy/lazy matching. Leaves s->pos at the
* first unprocessed byte. Stops early if the symbol buffer is near full.
@@ -3155,10 +3141,8 @@ static void rd_parse(struct rdeflate *s)
s->prev_lit = prev_lit;
}
/* flush a deferred match/literal at true end of input, or at a sync
* flush once all the input given so far is in */
if ((s->final_in || (s->flush_req && s->in_pos >= s->in_size))
&& s->pos >= end && s->have_prev
/* flush a deferred match/literal at true end of input */
if (s->final_in && s->pos >= end && s->have_prev
&& s->nsyms < RD_BLOCK_SYMS - 2)
{
s->have_prev = 0;
@@ -3902,33 +3886,6 @@ int rdeflate_process(void *data, size_t *read, size_t *wrote)
block_ready = 1;
is_final = 1;
}
/* sync flush: once all the input given is parsed, the pending
* symbols go out as a block, then an empty stored block ends
* the output on a byte boundary (zlib's Z_SYNC_FLUSH). The
* window is kept, so matches still reach across it. */
if (!block_ready && s->flush_req && !s->final_in
&& s->in_pos >= s->in_size && s->pos >= s->win_len
&& !s->have_prev)
{
if (s->nsyms)
block_ready = 1;
else
{
if (s->flush_req == 1)
{
rd_putbits(s, 0, 3); /* BFINAL=0, BTYPE=00 */
if (s->bitcnt & 7)
rd_putbits(s, 0, 8 - (s->bitcnt & 7));
rd_putbits(s, 0x0000, 16);
rd_putbits(s, 0xffff, 16);
s->flush_req = 2;
}
if (!rd_flush_bytes(s))
goto suspend;
s->flush_req = 0;
goto suspend;
}
}
if (!block_ready) /* need more input */
goto suspend;
s->block_final = is_final;
@@ -1,242 +0,0 @@
/* Copyright (C) 2010-2026 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (encoding_shiftjis.c).
* ---------------------------------------------------------------------------------------
*
* Permission is hereby granted, free of charge,
* to any person obtaining a copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <stdint.h>
#include <stddef.h>
#include <encodings/shiftjis.h>
#include "encoding_shiftjis_tables.h"
/* The row of sjis_decode for lead octet @b, or -1 */
static int sjis_row(unsigned b)
{
if (b >= 0x81 && b <= 0x9F)
return (int)(b - 0x81);
if (b >= 0xE0 && b <= 0xEF)
return (int)(b - 0xE0 + 31);
if (b >= 0xFA && b <= 0xFC)
return (int)(b - 0xFA + 47);
return -1;
}
/* Puts @cp at @out + *pos as UTF-8 if it fits in @cap octets */
static int sjis_put_utf8(char *out, size_t cap, size_t *pos, uint32_t cp)
{
size_t n = cp < 0x80 ? 1 : cp < 0x800 ? 2 : 3;
char *p = out + *pos;
if (cap - *pos < n)
return 0;
if (n == 1)
p[0] = (char)cp;
else if (n == 2)
{
p[0] = (char)(0xC0 | (cp >> 6));
p[1] = (char)(0x80 | (cp & 0x3F));
}
else
{
p[0] = (char)(0xE0 | (cp >> 12));
p[1] = (char)(0x80 | ((cp >> 6) & 0x3F));
p[2] = (char)(0x80 | (cp & 0x3F));
}
*pos += n;
return 1;
}
size_t sjis_to_utf8(char *out, size_t out_size, const char *in, size_t in_len)
{
const unsigned char *s = (const unsigned char*)in;
size_t i = 0, pos = 0;
if (!out_size)
return 0;
while (i < in_len)
{
unsigned b = s[i];
uint32_t cp;
int row;
if (b < 0x80)
{
cp = b;
i++;
}
else if (b >= 0xA1 && b <= 0xDF)
{
/* half-width katakana */
cp = 0xFF61 + (b - 0xA1);
i++;
}
else
{
unsigned t;
if ((row = sjis_row(b)) < 0 || i + 1 >= in_len)
{
i++;
continue;
}
t = s[i + 1];
if (t < 0x40 || t > 0xFC || !(cp = sjis_decode[row][t - 0x40]))
{
i++;
continue;
}
i += 2;
}
if (!sjis_put_utf8(out, out_size - 1, &pos, cp))
break;
}
out[pos] = '\0';
return pos;
}
/* The two-octet code for @cp, or 0 */
static unsigned sjis_lookup(uint32_t cp)
{
size_t lo = 0, hi = SJIS_ENCODE_COUNT;
while (lo < hi)
{
size_t mid = lo + (hi - lo) / 2;
if (sjis_encode[mid][0] < cp)
lo = mid + 1;
else
hi = mid;
}
return lo < SJIS_ENCODE_COUNT && sjis_encode[lo][0] == cp ? sjis_encode[lo][1] : 0;
}
/* The code point UTF-8 starts at @s (@len octets left), its length at
* @n; 0 at @n where the octet starts no valid character */
static uint32_t sjis_utf8_next(const unsigned char *s, size_t len, size_t *n)
{
unsigned b = s[0];
uint32_t cp, min;
size_t k, more;
*n = 0;
if (b < 0x80)
{
*n = 1;
return b;
}
if (b >= 0xC2 && b <= 0xDF)
{
more = 1;
cp = b & 0x1F;
min = 0x80;
}
else if (b >= 0xE0 && b <= 0xEF)
{
more = 2;
cp = b & 0x0F;
min = 0x800;
}
else if (b >= 0xF0 && b <= 0xF4)
{
more = 3;
cp = b & 0x07;
min = 0x10000;
}
else
return 0;
if (len <= more)
return 0;
for (k = 1; k <= more; k++)
{
if ((s[k] & 0xC0) != 0x80)
return 0;
cp = (cp << 6) | (s[k] & 0x3F);
}
if (cp < min || cp > 0x10FFFF || (cp >= 0xD800 && cp <= 0xDFFF))
return 0;
*n = more + 1;
return cp;
}
size_t utf8_to_sjis(char *out, size_t out_size, const char *in, size_t in_len)
{
const unsigned char *s = (const unsigned char*)in;
size_t i = 0, pos = 0;
if (!out_size)
return 0;
while (i < in_len)
{
size_t n;
uint32_t cp = sjis_utf8_next(s + i, in_len - i, &n);
unsigned code;
if (!n)
{
i++;
continue;
}
i += n;
if (cp < 0x80)
code = cp;
else if (cp >= 0xFF61 && cp <= 0xFF9F)
code = 0xA1 + (cp - 0xFF61);
else if (!(code = sjis_lookup(cp)))
continue;
if (code > 0xFF)
{
if (out_size - 1 - pos < 2)
break;
out[pos++] = (char)(code >> 8);
out[pos++] = (char)(code & 0xFF);
}
else
{
if (out_size - 1 - pos < 1)
break;
out[pos++] = (char)code;
}
}
out[pos] = '\0';
return pos;
}
/* Code page 1252's 0x80-0x9F; 0 where it has nothing */
static const uint16_t cp1252_high[32] = {
0x20AC, 0, 0x201A, 0x0192, 0x201E, 0x2026, 0x2020, 0x2021,
0x02C6, 0x2030, 0x0160, 0x2039, 0x0152, 0, 0x017D, 0,
0, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014,
0x02DC, 0x2122, 0x0161, 0x203A, 0x0153, 0, 0x017E, 0x0178
};
size_t cp1252_to_utf8(char *out, size_t out_size, const char *in, size_t in_len)
{
const unsigned char *s = (const unsigned char*)in;
size_t i, pos = 0;
if (!out_size)
return 0;
for (i = 0; i < in_len; i++)
{
uint32_t cp = s[i];
if (cp >= 0x80 && cp <= 0x9F && !(cp = cp1252_high[cp - 0x80]))
continue;
if (!sjis_put_utf8(out, out_size - 1, &pos, cp))
break;
}
out[pos] = '\0';
return pos;
}
File diff suppressed because it is too large. Load diff
-185
View File
@@ -1,185 +0,0 @@
/* Copyright (C) 2010-2026 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (encoding_xxh32.c).
* ---------------------------------------------------------------------------------------
*
* Permission is hereby granted, free of charge,
* to any person obtaining a copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <string.h>
#if defined(_MSC_VER)
#include <stdlib.h>
#endif
#include <retro_inline.h>
#include <retro_endianness.h>
#include <encodings/xxh32.h>
#define XXH32_P1 0x9E3779B1U
#define XXH32_P2 0x85EBCA77U
#define XXH32_P3 0xC2B2AE3DU
#define XXH32_P4 0x27D4EB2FU
#define XXH32_P5 0x165667B1U
#if defined(_MSC_VER)
#define XXH32_ROTL(x, r) _rotl((x), (r))
#else
#define XXH32_ROTL(x, r) (((x) << (r)) | ((x) >> (32 - (r))))
#endif
#define XXH32_ROUND(acc, in) \
((acc) += (in) * XXH32_P2, (acc) = XXH32_ROTL((acc), 13), \
(acc) *= XXH32_P1)
static INLINE uint32_t xxh32_rd32(const uint8_t *p)
{
uint32_t v;
memcpy(&v, p, 4);
return swap_if_big32(v);
}
/* The whole stripes of @p up to @end, at least one, through the lanes
* @v; returns where the stripes stop. */
static INLINE const uint8_t *xxh32_stripes(uint32_t *v, const uint8_t *p,
const uint8_t *end)
{
uint32_t v1 = v[0];
uint32_t v2 = v[1];
uint32_t v3 = v[2];
uint32_t v4 = v[3];
const uint8_t *stop = p + ((size_t)(end - p) & ~(size_t)15);
do
{
XXH32_ROUND(v1, xxh32_rd32(p));
XXH32_ROUND(v2, xxh32_rd32(p + 4));
XXH32_ROUND(v3, xxh32_rd32(p + 8));
XXH32_ROUND(v4, xxh32_rd32(p + 12));
p += 16;
} while (p != stop);
v[0] = v1;
v[1] = v2;
v[2] = v3;
v[3] = v4;
return p;
}
static INLINE uint32_t xxh32_converge(const uint32_t *v)
{
return XXH32_ROTL(v[0], 1) + XXH32_ROTL(v[1], 7)
+ XXH32_ROTL(v[2], 12) + XXH32_ROTL(v[3], 18);
}
/* The last @len (under 16) octets at @p, and the avalanche: fours, then
* single octets */
static INLINE uint32_t xxh32_finish(uint32_t h, const uint8_t *p, size_t len)
{
for (; len >= 4; len -= 4, p += 4)
{
h += xxh32_rd32(p) * XXH32_P3;
h = XXH32_ROTL(h, 17) * XXH32_P4;
}
for (; len; len--)
{
h += (uint32_t)*p++ * XXH32_P5;
h = XXH32_ROTL(h, 11) * XXH32_P1;
}
h ^= h >> 15;
h *= XXH32_P2;
h ^= h >> 13;
h *= XXH32_P3;
h ^= h >> 16;
return h;
}
static void xxh32_lanes(uint32_t *v, uint32_t seed)
{
v[0] = seed + XXH32_P1 + XXH32_P2;
v[1] = seed + XXH32_P2;
v[2] = seed;
v[3] = seed - XXH32_P1;
}
uint32_t xxh32(const void *data, size_t len, uint32_t seed)
{
const uint8_t *p = (const uint8_t*)data;
uint32_t h;
if (len >= 16)
{
uint32_t v[4];
xxh32_lanes(v, seed);
p = xxh32_stripes(v, p, p + len);
h = xxh32_converge(v);
}
else
h = seed + XXH32_P5;
return xxh32_finish(h + (uint32_t)len, p, len & 15);
}
void xxh32_reset(xxh32_state_t *s, uint32_t seed)
{
xxh32_lanes(s->v, seed);
s->total = 0;
s->large = 0;
s->memsize = 0;
}
void xxh32_update(xxh32_state_t *s, const void *data, size_t len)
{
const uint8_t *p = (const uint8_t*)data;
const uint8_t *end = p + len;
if (!len)
return;
s->total += (uint32_t)len;
s->large |= (len >= 16) | (s->total >= 16);
/* not yet a stripe */
if (s->memsize + len < 16)
{
memcpy(s->mem + s->memsize, p, len);
s->memsize += (uint32_t)len;
return;
}
/* the stripe begun before, made whole */
if (s->memsize)
{
size_t fill = 16 - s->memsize;
memcpy(s->mem + s->memsize, p, fill);
xxh32_stripes(s->v, s->mem, s->mem + 16);
p += fill;
s->memsize = 0;
}
if (end - p >= 16)
p = xxh32_stripes(s->v, p, end);
if (p != end)
{
memcpy(s->mem, p, (size_t)(end - p));
s->memsize = (uint32_t)(end - p);
}
}
uint32_t xxh32_digest(const xxh32_state_t *s)
{
uint32_t h = s->large
? xxh32_converge(s->v)
: s->v[2] + XXH32_P5;
return xxh32_finish(h + s->total, s->mem, s->memsize);
}
@@ -1,61 +0,0 @@
# python3 gen_sjis_tables.py > encoding_shiftjis_tables.h
#
# Writes encoding_shiftjis_tables.h: Shift-JIS as Windows code page 932
# has it (JIS X 0208 with the NEC and IBM extensions), from Python's
# cp932 codec. The user-defined area F040-F9FC and the single octets
# 0x80, 0xA0 and 0xFD-0xFF, which code page 932 sends to the Private Use
# Area, are left out.
import sys
def lead_ok(l):
return 0x81 <= l <= 0x9F or 0xE0 <= l <= 0xEF or 0xFA <= l <= 0xFC
leads = [l for l in range(0x81, 0xFD) if lead_ok(l)]
decode = []
pairs = {}
for l in leads:
row = []
for t in range(0x40, 0xFD):
u = 0
try:
s = bytes([l, t]).decode('cp932')
if len(s) == 1 and not (0xE000 <= ord(s) <= 0xF8FF):
u = ord(s)
except UnicodeDecodeError:
pass
row.append(u)
decode.append(row)
for cp in range(0x80, 0x10000):
if 0xD800 <= cp < 0xE000 or 0xE000 <= cp <= 0xF8FF:
continue
try:
e = chr(cp).encode('cp932')
except UnicodeEncodeError:
continue
if len(e) == 2 and lead_ok(e[0]):
pairs[cp] = (e[0] << 8) | e[1]
out = sys.stdout
out.write('/* Generated by gen_sjis_tables.py from code page 932, as Python\'s\n'
' * cp932 codec has it; do not edit. */\n'
'#ifndef LIBRETRO_ENCODING_SHIFTJIS_TABLES_H\n'
'#define LIBRETRO_ENCODING_SHIFTJIS_TABLES_H\n\n'
'#include <stdint.h>\n\n')
out.write('/* Unicode for lead octet L (rows: 0x81-0x9F, 0xE0-0xEF, 0xFA-0xFC)\n'
' * and trail octet 0x40-0xFC; 0 where nothing is mapped. */\n')
out.write('static const uint16_t sjis_decode[%d][189] = {\n' % len(leads))
for l, row in zip(leads, decode):
out.write(' /* 0x%02X */ {\n' % l)
for i in range(0, len(row), 10):
out.write(' ' + ','.join('0x%04X' % v for v in row[i:i+10]) + ',\n')
out.write(' },\n')
out.write('};\n\n')
keys = sorted(pairs)
out.write('/* Unicode code points with their two-octet Shift-JIS codes, sorted\n'
' * by code point for a binary search. */\n')
out.write('#define SJIS_ENCODE_COUNT %d\n' % len(keys))
out.write('static const uint16_t sjis_encode[SJIS_ENCODE_COUNT][2] = {\n')
for i in range(0, len(keys), 6):
out.write(' ' + ','.join('{0x%04X,0x%04X}' % (k, pairs[k]) for k in keys[i:i+6]) + ',\n')
out.write('};\n\n#endif\n')
+43 -5
View File
@@ -599,14 +599,52 @@ struct string_list *file_archive_get_file_list(const char *path,
/* Copies a complete temporary file over a target it could not be
* renamed onto, with the platform's copy primitive where there is one.
* Only for filesystems that refuse the rename; an atomic replacement
* is no longer possible there, which is what writing the member in
* place always meant. */
* renamed onto, and removes it. Only for filesystems that refuse the
* rename; an atomic replacement is no longer possible there, which is
* what writing the member in place always meant. */
static bool file_archive_pending_copy_in_place(const char *temp_path,
const char *path)
{
return filestream_copy(temp_path, path) == 0;
bool ok = true;
uint8_t *buf;
RFILE *in;
RFILE *out;
if (!(buf = (uint8_t*)malloc(65536)))
return false;
if (!(in = filestream_open(temp_path, RETRO_VFS_FILE_ACCESS_READ,
RETRO_VFS_FILE_ACCESS_HINT_NONE)))
{
free(buf);
return false;
}
if (!(out = filestream_open(path, RETRO_VFS_FILE_ACCESS_WRITE,
RETRO_VFS_FILE_ACCESS_HINT_NONE)))
{
filestream_close(in);
free(buf);
return false;
}
for (;;)
{
int64_t rd = filestream_read(in, buf, 65536);
if (rd < 0)
ok = false;
if (rd <= 0)
break;
if (filestream_write(out, buf, rd) != rd)
{
ok = false;
break;
}
}
filestream_close(in);
if (filestream_close(out) != 0)
ok = false;
free(buf);
return ok;
}
/* Puts a completed member in place. Written beside the file and
+1 -2
View File
@@ -390,8 +390,7 @@ static int64_t bz2_file_read(const char *path, const char *needle,
if (optional_outfile)
{
RFILE *out = filestream_open(optional_outfile,
RETRO_VFS_FILE_ACCESS_WRITE,
RETRO_VFS_FILE_ACCESS_HINT_SEQUENTIAL_BULK);
RETRO_VFS_FILE_ACCESS_WRITE, RETRO_VFS_FILE_ACCESS_HINT_NONE);
ok = out && bz2_pass(&src, file, filestream_get_size(file),
bz2_write, out);
if (out)
+50 -47
View File
@@ -185,18 +185,6 @@ static INLINE uint64_t read_le64(const uint8_t *data)
return (uint64_t)read_le(data, 4) | ((uint64_t)read_le(data + 4, 4) << 32);
}
/* @len octets at @off: one read at the offset, or a seek and a read
* where the file has none */
static int64_t zip_read_at(RFILE *f, void *buf, int64_t len, int64_t off)
{
int64_t got = filestream_read_at(f, buf, len, off);
if (got >= 0)
return got;
if (filestream_seek(f, off, RETRO_VFS_SEEK_POSITION_START) < 0)
return -1;
return filestream_read(f, buf, len);
}
static void zip_context_free_stream(
zip_context_t *zip_context, bool keep_decompressed)
{
@@ -286,16 +274,17 @@ static bool zip_bzip2_fill(struct file_archive_transfer *state,
uint64_t to = taken + cap;
if (to > zip_context->csize)
to = zip_context->csize;
filestream_seek(state->archive_file,
(int64_t)(zip_context->fdoffset + zip_context->boffset),
RETRO_VFS_SEEK_POSITION_START);
while (zip_context->boffset < to)
{
size_t at = (size_t)(zip_context->boffset % cap);
size_t n = cap - at;
if (n > to - zip_context->boffset)
n = (size_t)(to - zip_context->boffset);
if (zip_read_at(state->archive_file, zip_context->tmpbuf + at,
(int64_t)n,
(int64_t)(zip_context->fdoffset + zip_context->boffset))
!= (int64_t)n)
if (filestream_read(state->archive_file, zip_context->tmpbuf + at,
(int64_t)n) != (int64_t)n)
return false;
zip_context->boffset += n;
}
@@ -363,8 +352,8 @@ static const uint8_t *zip_member_whole(struct file_archive_transfer *state,
*buf = p;
*cap = (size_t)csize;
}
if (zip_read_at(state->archive_file, *buf, (int64_t)csize, off)
!= (int64_t)csize)
filestream_seek(state->archive_file, off, RETRO_VFS_SEEK_POSITION_START);
if (filestream_read(state->archive_file, *buf, csize) != (int64_t)csize)
return NULL;
return *buf;
}
@@ -455,8 +444,8 @@ static bool zlib_stream_decompress_data_to_file_init(
else
#endif
{
if (zip_read_at(state->archive_file, local_header_buf, 4,
(int64_t)local + 26) != 4)
filestream_seek(state->archive_file, (int64_t)local + 26, RETRO_VFS_SEEK_POSITION_START);
if (filestream_read(state->archive_file, local_header_buf, 4) != 4)
return false;
local_header = local_header_buf;
}
@@ -529,9 +518,11 @@ static bool zlib_stream_decompress_data_to_file_init(
else
#endif
{
filestream_seek(state->archive_file, offsetData,
RETRO_VFS_SEEK_POSITION_START);
if ( csize < sizeof(hdr)
|| zip_read_at(state->archive_file, hdr, sizeof(hdr),
offsetData) != (int64_t)sizeof(hdr))
|| filestream_read(state->archive_file, hdr, sizeof(hdr))
!= (int64_t)sizeof(hdr))
return false;
}
if ( csize < sizeof(hdr)
@@ -717,10 +708,10 @@ static int zlib_stream_decompress_data_to_file_iterate(
#endif
{
/* Read the entire file to memory */
if (zip_read_at(state->archive_file,
zip_context->decompressed_data,
(int64_t)zip_context->usize, zip_context->fdoffset)
!= (int64_t)zip_context->usize)
filestream_seek(state->archive_file, zip_context->fdoffset, RETRO_VFS_SEEK_POSITION_START);
if (filestream_read(state->archive_file,
zip_context->decompressed_data,
zip_context->usize) != (int64_t)zip_context->usize)
return -1;
}
@@ -906,9 +897,11 @@ static int zlib_stream_decompress_data_to_file_iterate(
size_t k = left < room ? (size_t)left : room;
if (k)
{
if (zip_read_at(state->archive_file,
zip_context->tmpbuf + zip_context->in_have, (int64_t)k,
(int64_t)(zip_context->fdoffset + zip_context->boffset))
filestream_seek(state->archive_file,
(int64_t)(zip_context->fdoffset + zip_context->boffset),
RETRO_VFS_SEEK_POSITION_START);
if (filestream_read(state->archive_file,
zip_context->tmpbuf + zip_context->in_have, (int64_t)k)
!= (int64_t)k)
return -1;
zip_context->boffset += k;
@@ -978,9 +971,11 @@ static int zlib_stream_decompress_data_to_file_iterate(
size_t k = left < room ? (size_t)left : room;
if (k)
{
if (zip_read_at(state->archive_file,
zip_context->tmpbuf + zip_context->in_have, (int64_t)k,
(int64_t)(zip_context->fdoffset + zip_context->boffset))
filestream_seek(state->archive_file,
(int64_t)(zip_context->fdoffset + zip_context->boffset),
RETRO_VFS_SEEK_POSITION_START);
if (filestream_read(state->archive_file,
zip_context->tmpbuf + zip_context->in_have, (int64_t)k)
!= (int64_t)k)
return -1;
zip_context->boffset += k;
@@ -1073,11 +1068,12 @@ static int zlib_stream_decompress_data_to_file_iterate(
? RZSTD_PROCESS_END : RZSTD_PROCESS_ERROR;
else
{
filestream_seek(state->archive_file,
(int64_t)(zip_context->fdoffset + zip_context->boffset),
RETRO_VFS_SEEK_POSITION_START);
if ( want > zip_context->csize - zip_context->boffset
|| zip_read_at(state->archive_file, zip_context->tmpbuf,
(int64_t)want,
(int64_t)(zip_context->fdoffset + zip_context->boffset))
!= (int64_t)want
|| filestream_read(state->archive_file, zip_context->tmpbuf,
(int64_t)want) != (int64_t)want
|| rzstd_blocks_give((rzstd_blocks_t*)zip_context->zs,
zip_context->tmpbuf, want, &blk, &len)
!= RZSTD_PROCESS_NEXT)
@@ -1449,8 +1445,9 @@ static int zip_parse_file_init(file_archive_transfer_t *state,
else
read_pos = MAX(read_pos - read_block + 21, 0);
if (zip_read_at(state->archive_file, footer_buf, read_block,
read_pos) != read_block)
/* Seek to read_pos and read read_block bytes. */
filestream_seek(state->archive_file, read_pos, RETRO_VFS_SEEK_POSITION_START);
if (filestream_read(state->archive_file, footer_buf, read_block) != read_block)
return -1;
footer = footer_buf + read_block - 22;
@@ -1492,7 +1489,9 @@ static int zip_parse_file_init(file_archive_transfer_t *state,
loc = map + (size_t)(at - 20);
else
{
if (zip_read_at(state->archive_file, loc_buf, 20, at - 20) != 20)
filestream_seek(state->archive_file, at - 20,
RETRO_VFS_SEEK_POSITION_START);
if (filestream_read(state->archive_file, loc_buf, 20) != 20)
return -1;
}
if (read_le(loc, 4) != ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIGNATURE)
@@ -1504,8 +1503,9 @@ static int zip_parse_file_init(file_archive_transfer_t *state,
rec = map + (size_t)rec_off;
else
{
if (zip_read_at(state->archive_file, rec_buf, 56, (int64_t)rec_off)
!= 56)
filestream_seek(state->archive_file, (int64_t)rec_off,
RETRO_VFS_SEEK_POSITION_START);
if (filestream_read(state->archive_file, rec_buf, 56) != 56)
return -1;
}
if (read_le(rec, 4) != ZIP64_END_OF_CENTRAL_DIR_SIGNATURE)
@@ -1576,8 +1576,8 @@ static int zip_parse_file_init(file_archive_transfer_t *state,
if (!map)
{
if (zip_read_at(state->archive_file, zip_context->directory,
directory_size, directory_offset) != directory_size)
filestream_seek(state->archive_file, directory_offset, RETRO_VFS_SEEK_POSITION_START);
if (filestream_read(state->archive_file, zip_context->directory, directory_size) != directory_size)
{
free(zip_context);
return -1;
@@ -1837,8 +1837,9 @@ static int file_archive_entry_source_capture(
else
#endif
{
if (zip_read_at(state->archive_file, local_header_buf, 4,
(int64_t)local + 26) != 4)
filestream_seek(state->archive_file, (int64_t)local + 26,
RETRO_VFS_SEEK_POSITION_START);
if (filestream_read(state->archive_file, local_header_buf, 4) != 4)
return -1;
local_header = local_header_buf;
}
@@ -1963,8 +1964,10 @@ int64_t file_archive_entry_source_read(file_archive_entry_source_t *s,
else
#endif
{
if (zip_read_at(s->state.archive_file, dst, n,
(int64_t)(s->fdoffset + s->out_off)) != n)
filestream_seek(s->state.archive_file,
(int64_t)(s->fdoffset + s->out_off),
RETRO_VFS_SEEK_POSITION_START);
if (filestream_read(s->state.archive_file, dst, n) != n)
return -1;
}
s->out_off += (uint64_t)n;
+11 -13
View File
@@ -832,7 +832,7 @@ static void config_file_get_realpath(char *s, size_t len,
}
}
static bool config_file_add_sub_conf(config_file_t *conf, char *path,
static void config_file_add_sub_conf(config_file_t *conf, char *path,
char *s, size_t len, config_file_cb_t *cb)
{
struct config_include_list *node = (struct config_include_list*)
@@ -841,7 +841,12 @@ static bool config_file_add_sub_conf(config_file_t *conf, char *path,
if (node)
{
node->next = NULL;
node->path = path;
/* Add include list */
if (!(node->path = strdup(path)))
{
free(node);
goto realpath;
}
/* Order is user-visible - config_file_dump() writes the
* '#include' lines back in list order - so this appends rather
@@ -854,9 +859,9 @@ static bool config_file_add_sub_conf(config_file_t *conf, char *path,
conf->includes_tail = node;
}
realpath:
config_file_get_realpath(s, len, path,
conf->path);
return node != NULL;
}
size_t config_file_add_reference(config_file_t *conf, char *path)
@@ -1123,7 +1128,7 @@ static bool config_file_parse_line(config_file_t *conf,
if (include_found)
{
config_file_t sub_conf;
char *real_path;
char real_path[PATH_MAX_LENGTH];
char *include_line = comment + (sizeof("include ")-1);
if (*include_line == '\0')
return false;
@@ -1135,14 +1140,8 @@ static bool config_file_parse_line(config_file_t *conf,
free(path);
return false;
}
if (!(real_path = (char*)malloc(PATH_MAX_LENGTH)))
{
free(path);
return false;
}
if (config_file_add_sub_conf(conf, path,
real_path, PATH_MAX_LENGTH, cb))
path = NULL; /* The include list owns the parsed path. */
config_file_add_sub_conf(conf, path,
real_path, sizeof(real_path), cb);
config_file_initialize(&sub_conf);
/* Includes are fetched the same way their parent was. */
sub_conf.io = conf->io;
@@ -1170,7 +1169,6 @@ static bool config_file_parse_line(config_file_t *conf,
* NULL/transferred, so the call is equally correct
* there. */
config_file_deinitialize(&sub_conf);
free(real_path);
}
/* Starting a line with an 'reference' directive
* sets the reference path */
-168
View File
@@ -254,174 +254,6 @@ bool path_rmdir(const char *dir)
return retro_vfs_rmdir_impl(dir) == 0;
}
static bool path_is_dot_entry(const char *name)
{
return name[0] == '.'
&& (name[1] == '\0' || (name[1] == '.' && name[2] == '\0'));
}
/* Appends the separator and @name to the @len characters of @path,
* a PATH_MAX_LENGTH buffer. Returns the new length, or 0 if it
* does not fit. */
static size_t path_tree_append(char *path, size_t len, const char *name)
{
size_t name_len = strlen(name);
if (len + 1 + name_len >= PATH_MAX_LENGTH)
return 0;
path[len] = PATH_DEFAULT_SLASH_C();
memcpy(path + len + 1, name, name_len + 1);
return len + 1 + name_len;
}
/* Drops trailing separators, keeping a root's. Returns the length. */
static size_t path_tree_trim(char *path)
{
size_t len = strlen(path);
while (len > 1 && (path[len - 1] == '/' || path[len - 1] == '\\')
&& path[len - 2] != ':')
path[--len] = '\0';
return len;
}
/* Empties and removes the directory in the first @len characters of
* @path, which grows in place with each entry's name. */
static bool path_remove_tree_dir(char *path, size_t len)
{
bool ok = true;
libretro_vfs_implementation_dir *dir =
retro_vfs_opendir_impl(path, true);
if (!dir)
return false;
while (retro_vfs_readdir_impl(dir))
{
size_t entry_len;
const char *name = retro_vfs_dirent_get_name_impl(dir);
if (!name || path_is_dot_entry(name))
continue;
if (!(entry_len = path_tree_append(path, len, name)))
{
ok = false;
continue;
}
if (retro_vfs_dirent_is_dir_impl(dir))
{
/* An empty directory goes at once, and so does a link to
* one (rmdir on Windows, unlink elsewhere): only a real
* directory with something in it is walked. */
if ( retro_vfs_rmdir_impl(path) != 0
&& retro_vfs_file_remove_impl(path) != 0
&& !path_remove_tree_dir(path, entry_len))
ok = false;
}
else if (retro_vfs_file_remove_impl(path) != 0)
ok = false;
}
retro_vfs_closedir_impl(dir);
path[len] = '\0';
return retro_vfs_rmdir_impl(path) == 0 && ok;
}
bool path_remove_tree(const char *path)
{
bool ok;
size_t len;
char *buf;
if (!path || !*path)
return false;
/* A file, a link or an empty directory: no walk */
if ( retro_vfs_rmdir_impl(path) == 0
|| retro_vfs_file_remove_impl(path) == 0
|| !path_is_valid(path))
return true;
if (!path_is_directory(path))
return false;
if (!(buf = (char*)malloc(PATH_MAX_LENGTH)))
return false;
strlcpy(buf, path, PATH_MAX_LENGTH);
len = path_tree_trim(buf);
ok = path_remove_tree_dir(buf, len);
free(buf);
return ok;
}
static bool path_copy_tree_file(const char *src, const char *dst)
{
struct retro_vfs_copy_handle *copy =
retro_vfs_copy_begin_impl(src, dst, RETRO_VFS_COPY_OVERWRITE);
if (!copy)
return false;
/* The whole file in one step: the platform's copy primitive at
* full speed, no buffer of ours */
while (retro_vfs_copy_step_impl(copy, (int64_t)1 << 62, NULL, NULL)
== RETRO_VFS_COPY_RUNNING) { }
return retro_vfs_copy_close_impl(copy) == 0;
}
/* Copies the directory in the first @src_len characters of @src into
* the one in the first @dst_len of @dst; both grow in place. */
static bool path_copy_tree_dir(char *src, size_t src_len,
char *dst, size_t dst_len)
{
bool ok = true;
libretro_vfs_implementation_dir *dir;
if (!path_is_directory(dst) && !path_mkdir(dst))
return false;
if (!(dir = retro_vfs_opendir_impl(src, true)))
return false;
while (retro_vfs_readdir_impl(dir))
{
size_t src_entry, dst_entry;
const char *name = retro_vfs_dirent_get_name_impl(dir);
if (!name || path_is_dot_entry(name))
continue;
if ( !(src_entry = path_tree_append(src, src_len, name))
|| !(dst_entry = path_tree_append(dst, dst_len, name)))
ok = false;
else if (retro_vfs_dirent_is_dir_impl(dir))
{
if (!path_copy_tree_dir(src, src_entry, dst, dst_entry))
ok = false;
}
else if (!path_copy_tree_file(src, dst))
ok = false;
src[src_len] = '\0';
dst[dst_len] = '\0';
}
retro_vfs_closedir_impl(dir);
return ok;
}
bool path_copy_tree(const char *src, const char *dst)
{
bool ok;
char *src_buf;
char *dst_buf;
if (!src || !*src || !dst || !*dst)
return false;
if (!path_is_directory(src))
return path_copy_tree_file(src, dst);
if (!(src_buf = (char*)malloc(2 * PATH_MAX_LENGTH)))
return false;
dst_buf = src_buf + PATH_MAX_LENGTH;
strlcpy(src_buf, src, PATH_MAX_LENGTH);
strlcpy(dst_buf, dst, PATH_MAX_LENGTH);
ok = path_copy_tree_dir(src_buf, path_tree_trim(src_buf),
dst_buf, path_tree_trim(dst_buf));
free(src_buf);
return ok;
}
/**
* path_mkdir:
* @dir : directory
+34 -57
View File
@@ -396,13 +396,12 @@ struct r7z_archive
/* What a reader on another thread may look at while one thread calls
* r7z_archive_decode_step(): the buffer the folder is being decoded
* into in order, and how much of it is final. prog_state's low two
* bits are 0 when there is nothing to look at, 1 while it is being
* decoded, 2 when the folder is decoded and held; the rest count the
* changes, so that a reader that finds it the same after reading the
* others read them all from one (see r7z_progress_state()). */
retro_atomic_size_t prog_buf;
retro_atomic_size_t prog_folder;
* into in order, and how much of it is final. prog_state is 0 when
* there is nothing to look at, 1 while it is being decoded, 2 when
* the folder is decoded and held; the buffer and the folder are
* written before the state says they are there. */
const uint8_t *prog_buf;
uint32_t prog_folder;
retro_atomic_int_t prog_state;
retro_atomic_size_t prog_pos;
@@ -2333,26 +2332,6 @@ static int decode_encoded_header(r7z_archive_t *a, rd_t *r,
return res;
}
/* A new state, the count of changes moved on. Only the decoding thread
* writes it. */
static void r7z_progress_state(r7z_archive_t *a, int state)
{
unsigned n = (unsigned)retro_atomic_load_relaxed_int(&a->prog_state) >> 2;
retro_atomic_store_release_int(&a->prog_state,
(int)((((n + 1u) & 0x1FFFFFFFu) << 2) | (unsigned)state));
}
/* What a reader is to see from now on: nothing while it is written */
static void r7z_progress_set(r7z_archive_t *a, const uint8_t *buf,
uint32_t folder, size_t pos, int state)
{
r7z_progress_state(a, 0);
retro_atomic_store_release_size(&a->prog_buf, (size_t)(uintptr_t)buf);
retro_atomic_store_release_size(&a->prog_folder, folder);
retro_atomic_store_release_size(&a->prog_pos, pos);
r7z_progress_state(a, state);
}
/* The archive in memory (@data), or read through @read_cb. */
static int r7z_open(r7z_archive_t **out, const uint8_t *data, size_t len,
r7z_read_t read_cb, void *ud)
@@ -2407,8 +2386,6 @@ static int r7z_open(r7z_archive_t **out, const uint8_t *data, size_t len,
a->len = len;
a->read_cb = read_cb;
a->read_ud = ud;
retro_atomic_size_init(&a->prog_buf, 0);
retro_atomic_size_init(&a->prog_folder, 0);
retro_atomic_int_init(&a->prog_state, 0);
retro_atomic_size_init(&a->prog_pos, 0);
a->cached_folder = 0xFFFFFFFFu;
@@ -2494,7 +2471,7 @@ void r7z_archive_close(r7z_archive_t *a)
if (!a)
return;
decode_pending_reset(a);
r7z_progress_state(a, 0);
retro_atomic_store_release_int(&a->prog_state, 0);
if (!a->cached_borrowed)
free(a->cached_data);
#ifdef HAVE_RBZIP2
@@ -2578,8 +2555,8 @@ static void decode_pending_reset(r7z_archive_t *a)
if (!a)
return;
/* (a folder decoded and held stays to be looked at: 2) */
if ((retro_atomic_load_relaxed_int(&a->prog_state) & 3) == 1)
r7z_progress_state(a, 0);
if (retro_atomic_load_acquire_int(&a->prog_state) == 1)
retro_atomic_store_release_int(&a->prog_state, 0);
if (!a->pend_in_borrowed)
free(a->pend_in);
if (!a->pend_pass)
@@ -2637,7 +2614,10 @@ static int coder_is_resumable(const coder_t *c)
/* The cached folder, decoded whole and checked, is there to be read. */
static void r7z_progress_held(r7z_archive_t *a)
{
r7z_progress_set(a, a->cached_data, a->cached_folder, a->cached_len, 2);
a->prog_buf = a->cached_data;
a->prog_folder = a->cached_folder;
retro_atomic_store_release_size(&a->prog_pos, a->cached_len);
retro_atomic_store_release_int(&a->prog_state, 2);
}
/* The stage that is being decoded writes its output in order, and is the
@@ -2645,7 +2625,7 @@ static void r7z_progress_held(r7z_archive_t *a)
* to be read (r7z_archive_decode_peek()). */
static void r7z_progress_at(r7z_archive_t *a, size_t pos)
{
if ((retro_atomic_load_relaxed_int(&a->prog_state) & 3) == 1)
if (retro_atomic_load_acquire_int(&a->prog_state) == 1)
retro_atomic_store_release_size(&a->prog_pos, pos);
}
@@ -2849,7 +2829,10 @@ static int decode_stage_begin(r7z_archive_t *a, const folder_t *f)
* folder will be held in: its progress can be watched. */
if (a->pend_coder + 1 == f->num_coders)
{
r7z_progress_set(a, a->pend_out, a->pend_folder, 0, 1);
a->prog_buf = a->pend_out;
a->prog_folder = a->pend_folder;
retro_atomic_store_release_size(&a->prog_pos, 0);
retro_atomic_store_release_int(&a->prog_state, 1);
}
/* Stand up a decoder that survives between slices. */
@@ -3255,7 +3238,7 @@ static int decode_folder_bcj2_slice(r7z_archive_t *a, uint32_t fi,
return R7Z_ERROR_CRC;
}
r7z_progress_state(a, 0);
retro_atomic_store_release_int(&a->prog_state, 0);
r7z_cache_hold(a, a->pend_b2dst, a->pend_b2dstlen, fi, 0);
a->pend_b2dst = NULL;
@@ -3422,7 +3405,7 @@ static int decode_folder_slice(r7z_archive_t *a, uint32_t fi, int *done)
/* a folder no coder touched is held where it lies, when the
* archive is in memory */
r7z_progress_state(a, 0);
retro_atomic_store_release_int(&a->prog_state, 0);
r7z_cache_hold(a, a->pend_in, a->pend_in_len, fi, a->pend_in_borrowed);
r7z_progress_held(a);
@@ -3519,7 +3502,7 @@ int r7z_archive_extract_slice(r7z_archive_t *a, uint32_t index,
if ((res = decode_folder(a, e->folder, &folder_data, &folder_borrowed)) != R7Z_OK)
return res;
r7z_progress_state(a, 0);
retro_atomic_store_release_int(&a->prog_state, 0);
r7z_cache_hold(a, folder_data,
(size_t)a->folders[e->folder].unpack_size, e->folder,
folder_borrowed);
@@ -3580,7 +3563,7 @@ int r7z_archive_extract(r7z_archive_t *a, uint32_t index,
if (res != R7Z_OK)
return res;
r7z_progress_state(a, 0);
retro_atomic_store_release_int(&a->prog_state, 0);
r7z_cache_hold(a, folder_data,
(size_t)a->folders[e->folder].unpack_size, e->folder,
folder_borrowed);
@@ -3651,7 +3634,7 @@ int r7z_archive_extract_detach(r7z_archive_t *a, uint32_t index,
else
{
int borrowed = 0;
r7z_progress_state(a, 0);
retro_atomic_store_release_int(&a->prog_state, 0);
r7z_cache_hold(a, NULL, 0, 0xFFFFFFFFu, 0);
if ((res = decode_folder(a, e->folder, &buf, &borrowed)) != R7Z_OK)
return res;
@@ -3664,7 +3647,7 @@ int r7z_archive_extract_detach(r7z_archive_t *a, uint32_t index,
/* The folder's output is the member: hand the buffer over rather
* than keep it cached and copy it. */
r7z_progress_state(a, 0);
retro_atomic_store_release_int(&a->prog_state, 0);
a->cached_data = NULL;
a->cached_len = 0;
a->cached_folder = 0xFFFFFFFFu;
@@ -3711,7 +3694,7 @@ int r7z_archive_entry_borrow(r7z_archive_t *a, uint32_t index,
{
if ((res = decode_folder(a, e->folder, &folder_data, &folder_borrowed)) != R7Z_OK)
return res;
r7z_progress_state(a, 0);
retro_atomic_store_release_int(&a->prog_state, 0);
r7z_cache_hold(a, folder_data,
(size_t)a->folders[e->folder].unpack_size, e->folder,
folder_borrowed);
@@ -3753,7 +3736,7 @@ int r7z_archive_decode_step(r7z_archive_t *a, uint32_t index)
if (a->cached_folder == e->folder && a->cached_data)
{
if ((retro_atomic_load_relaxed_int(&a->prog_state) & 3) != 2)
if (retro_atomic_load_acquire_int(&a->prog_state) != 2)
r7z_progress_held(a);
return R7Z_OK;
}
@@ -3767,7 +3750,7 @@ int r7z_archive_decode_step(r7z_archive_t *a, uint32_t index)
if ((res = decode_folder(a, e->folder, &folder_data, &folder_borrowed)) != R7Z_OK)
return res;
r7z_progress_state(a, 0);
retro_atomic_store_release_int(&a->prog_state, 0);
r7z_cache_hold(a, folder_data,
(size_t)a->folders[e->folder].unpack_size, e->folder,
folder_borrowed);
@@ -3779,7 +3762,7 @@ int r7z_archive_decode_step(r7z_archive_t *a, uint32_t index)
if (!done)
return R7Z_PENDING;
/* (a folder that went through the BCJ2 slicer says so only now) */
if ((retro_atomic_load_relaxed_int(&a->prog_state) & 3) != 2)
if (retro_atomic_load_acquire_int(&a->prog_state) != 2)
r7z_progress_held(a);
return R7Z_OK;
}
@@ -4822,7 +4805,7 @@ int r7z_archive_decode_peek(const r7z_archive_t *a, uint32_t index,
const uint8_t **data, size_t *avail)
{
const r7z_entry_t *e;
size_t pos, buf, folder;
size_t pos;
int state;
if (!a || !data || !avail || index >= a->num_entries)
@@ -4833,20 +4816,14 @@ int r7z_archive_decode_peek(const r7z_archive_t *a, uint32_t index,
if (e->is_dir)
return R7Z_ERROR_PARAM;
/* the state, what it says is there, and the state again: changed,
* and what was read may be from before and after */
state = retro_atomic_load_acquire_int((retro_atomic_int_t*)&a->prog_state);
if (!(state & 3))
return R7Z_OK;
folder = retro_atomic_load_acquire_size((retro_atomic_size_t*)&a->prog_folder);
buf = retro_atomic_load_acquire_size((retro_atomic_size_t*)&a->prog_buf);
pos = retro_atomic_load_acquire_size((retro_atomic_size_t*)&a->prog_pos);
if (retro_atomic_load_acquire_int((retro_atomic_int_t*)&a->prog_state) != state
|| folder != e->folder)
/* the state, and then what it says is there */
state = retro_atomic_load_acquire_int((retro_atomic_int_t*)&a->prog_state);
if (!state || a->prog_folder != e->folder)
return R7Z_OK;
pos = retro_atomic_load_acquire_size((retro_atomic_size_t*)&a->prog_pos);
if (e->offset_in_folder > (uint64_t)((size_t)-1))
return R7Z_ERROR_DATA;
*data = (const uint8_t*)(uintptr_t)buf + (size_t)e->offset_in_folder;
*data = a->prog_buf + (size_t)e->offset_in_folder;
if (pos > (size_t)e->offset_in_folder)
{
size_t have = pos - (size_t)e->offset_in_folder;
+385 -2
View File
@@ -216,8 +216,384 @@ static INLINE raac_v raac_v_set4(float a, float b, float c, float e)
#define RAAC_CB_INTENSITY 15
#define RAAC_CB_NOISE 13
#include "raac_tables.h"
static const uint16_t raac_hcb1_code[81] = {
0x07f8, 0x01f1, 0x07fd, 0x03f5, 0x0068, 0x03f0, 0x07f7, 0x01ec,
0x07f5, 0x03f1, 0x0072, 0x03f4, 0x0074, 0x0011, 0x0076, 0x01eb,
0x006c, 0x03f6, 0x07fc, 0x01e1, 0x07f1, 0x01f0, 0x0061, 0x01f6,
0x07f2, 0x01ea, 0x07fb, 0x01f2, 0x0069, 0x01ed, 0x0077, 0x0017,
0x006f, 0x01e6, 0x0064, 0x01e5, 0x0067, 0x0015, 0x0062, 0x0012,
0x0000, 0x0014, 0x0065, 0x0016, 0x006d, 0x01e9, 0x0063, 0x01e4,
0x006b, 0x0013, 0x0071, 0x01e3, 0x0070, 0x01f3, 0x07fe, 0x01e7,
0x07f3, 0x01ef, 0x0060, 0x01ee, 0x07f0, 0x01e2, 0x07fa, 0x03f3,
0x006a, 0x01e8, 0x0075, 0x0010, 0x0073, 0x01f4, 0x006e, 0x03f7,
0x07f6, 0x01e0, 0x07f9, 0x03f2, 0x0066, 0x01f5, 0x07ff, 0x01f7,
0x07f4
};
static const uint8_t raac_hcb1_bits[81] = {
11, 9, 11, 10, 7, 10, 11, 9, 11, 10, 7, 10, 7, 5, 7, 9,
7, 10, 11, 9, 11, 9, 7, 9, 11, 9, 11, 9, 7, 9, 7, 5,
7, 9, 7, 9, 7, 5, 7, 5, 1, 5, 7, 5, 7, 9, 7, 9,
7, 5, 7, 9, 7, 9, 11, 9, 11, 9, 7, 9, 11, 9, 11, 10,
7, 9, 7, 5, 7, 9, 7, 10, 11, 9, 11, 10, 7, 9, 11, 9,
11
};
static const uint16_t raac_hcb2_code[81] = {
0x01f3, 0x006f, 0x01fd, 0x00eb, 0x0023, 0x00ea, 0x01f7, 0x00e8,
0x01fa, 0x00f2, 0x002d, 0x0070, 0x0020, 0x0006, 0x002b, 0x006e,
0x0028, 0x00e9, 0x01f9, 0x0066, 0x00f8, 0x00e7, 0x001b, 0x00f1,
0x01f4, 0x006b, 0x01f5, 0x00ec, 0x002a, 0x006c, 0x002c, 0x000a,
0x0027, 0x0067, 0x001a, 0x00f5, 0x0024, 0x0008, 0x001f, 0x0009,
0x0000, 0x0007, 0x001d, 0x000b, 0x0030, 0x00ef, 0x001c, 0x0064,
0x001e, 0x000c, 0x0029, 0x00f3, 0x002f, 0x00f0, 0x01fc, 0x0071,
0x01f2, 0x00f4, 0x0021, 0x00e6, 0x00f7, 0x0068, 0x01f8, 0x00ee,
0x0022, 0x0065, 0x0031, 0x0002, 0x0026, 0x00ed, 0x0025, 0x006a,
0x01fb, 0x0072, 0x01fe, 0x0069, 0x002e, 0x00f6, 0x01ff, 0x006d,
0x01f6
};
static const uint8_t raac_hcb2_bits[81] = {
9, 7, 9, 8, 6, 8, 9, 8, 9, 8, 6, 7, 6, 5, 6, 7,
6, 8, 9, 7, 8, 8, 6, 8, 9, 7, 9, 8, 6, 7, 6, 5,
6, 7, 6, 8, 6, 5, 6, 5, 3, 5, 6, 5, 6, 8, 6, 7,
6, 5, 6, 8, 6, 8, 9, 7, 9, 8, 6, 8, 8, 7, 9, 8,
6, 7, 6, 4, 6, 8, 6, 7, 9, 7, 9, 7, 6, 8, 9, 7,
9
};
static const uint16_t raac_hcb3_code[81] = {
0x0000, 0x0009, 0x00ef, 0x000b, 0x0019, 0x00f0, 0x01eb, 0x01e6,
0x03f2, 0x000a, 0x0035, 0x01ef, 0x0034, 0x0037, 0x01e9, 0x01ed,
0x01e7, 0x03f3, 0x01ee, 0x03ed, 0x1ffa, 0x01ec, 0x01f2, 0x07f9,
0x07f8, 0x03f8, 0x0ff8, 0x0008, 0x0038, 0x03f6, 0x0036, 0x0075,
0x03f1, 0x03eb, 0x03ec, 0x0ff4, 0x0018, 0x0076, 0x07f4, 0x0039,
0x0074, 0x03ef, 0x01f3, 0x01f4, 0x07f6, 0x01e8, 0x03ea, 0x1ffc,
0x00f2, 0x01f1, 0x0ffb, 0x03f5, 0x07f3, 0x0ffc, 0x00ee, 0x03f7,
0x7ffe, 0x01f0, 0x07f5, 0x7ffd, 0x1ffb, 0x3ffa, 0xffff, 0x00f1,
0x03f0, 0x3ffc, 0x01ea, 0x03ee, 0x3ffb, 0x0ff6, 0x0ffa, 0x7ffc,
0x07f2, 0x0ff5, 0xfffe, 0x03f4, 0x07f7, 0x7ffb, 0x0ff7, 0x0ff9,
0x7ffa
};
static const uint8_t raac_hcb3_bits[81] = {
1, 4, 8, 4, 5, 8, 9, 9, 10, 4, 6, 9, 6, 6, 9, 9,
9, 10, 9, 10, 13, 9, 9, 11, 11, 10, 12, 4, 6, 10, 6, 7,
10, 10, 10, 12, 5, 7, 11, 6, 7, 10, 9, 9, 11, 9, 10, 13,
8, 9, 12, 10, 11, 12, 8, 10, 15, 9, 11, 15, 13, 14, 16, 8,
10, 14, 9, 10, 14, 12, 12, 15, 11, 12, 16, 10, 11, 15, 12, 12,
15
};
static const uint16_t raac_hcb4_code[81] = {
0x0007, 0x0016, 0x00f6, 0x0018, 0x0008, 0x00ef, 0x01ef, 0x00f3,
0x07f8, 0x0019, 0x0017, 0x00ed, 0x0015, 0x0001, 0x00e2, 0x00f0,
0x0070, 0x03f0, 0x01ee, 0x00f1, 0x07fa, 0x00ee, 0x00e4, 0x03f2,
0x07f6, 0x03ef, 0x07fd, 0x0005, 0x0014, 0x00f2, 0x0009, 0x0004,
0x00e5, 0x00f4, 0x00e8, 0x03f4, 0x0006, 0x0002, 0x00e7, 0x0003,
0x0000, 0x006b, 0x00e3, 0x0069, 0x01f3, 0x00eb, 0x00e6, 0x03f6,
0x006e, 0x006a, 0x01f4, 0x03ec, 0x01f0, 0x03f9, 0x00f5, 0x00ec,
0x07fb, 0x00ea, 0x006f, 0x03f7, 0x07f9, 0x03f3, 0x0fff, 0x00e9,
0x006d, 0x03f8, 0x006c, 0x0068, 0x01f5, 0x03ee, 0x01f2, 0x07f4,
0x07f7, 0x03f1, 0x0ffe, 0x03ed, 0x01f1, 0x07f5, 0x07fe, 0x03f5,
0x07fc
};
static const uint8_t raac_hcb4_bits[81] = {
4, 5, 8, 5, 4, 8, 9, 8, 11, 5, 5, 8, 5, 4, 8, 8,
7, 10, 9, 8, 11, 8, 8, 10, 11, 10, 11, 4, 5, 8, 4, 4,
8, 8, 8, 10, 4, 4, 8, 4, 4, 7, 8, 7, 9, 8, 8, 10,
7, 7, 9, 10, 9, 10, 8, 8, 11, 8, 7, 10, 11, 10, 12, 8,
7, 10, 7, 7, 9, 10, 9, 11, 11, 10, 12, 10, 9, 11, 11, 10,
11
};
static const uint16_t raac_hcb5_code[81] = {
0x1fff, 0x0ff7, 0x07f4, 0x07e8, 0x03f1, 0x07ee, 0x07f9, 0x0ff8,
0x1ffd, 0x0ffd, 0x07f1, 0x03e8, 0x01e8, 0x00f0, 0x01ec, 0x03ee,
0x07f2, 0x0ffa, 0x0ff4, 0x03ef, 0x01f2, 0x00e8, 0x0070, 0x00ec,
0x01f0, 0x03ea, 0x07f3, 0x07eb, 0x01eb, 0x00ea, 0x001a, 0x0008,
0x0019, 0x00ee, 0x01ef, 0x07ed, 0x03f0, 0x00f2, 0x0073, 0x000b,
0x0000, 0x000a, 0x0071, 0x00f3, 0x07e9, 0x07ef, 0x01ee, 0x00ef,
0x0018, 0x0009, 0x001b, 0x00eb, 0x01e9, 0x07ec, 0x07f6, 0x03eb,
0x01f3, 0x00ed, 0x0072, 0x00e9, 0x01f1, 0x03ed, 0x07f7, 0x0ff6,
0x07f0, 0x03e9, 0x01ed, 0x00f1, 0x01ea, 0x03ec, 0x07f8, 0x0ff9,
0x1ffc, 0x0ffc, 0x0ff5, 0x07ea, 0x03f3, 0x03f2, 0x07f5, 0x0ffb,
0x1ffe
};
static const uint8_t raac_hcb5_bits[81] = {
13, 12, 11, 11, 10, 11, 11, 12, 13, 12, 11, 10, 9, 8, 9, 10,
11, 12, 12, 10, 9, 8, 7, 8, 9, 10, 11, 11, 9, 8, 5, 4,
5, 8, 9, 11, 10, 8, 7, 4, 1, 4, 7, 8, 11, 11, 9, 8,
5, 4, 5, 8, 9, 11, 11, 10, 9, 8, 7, 8, 9, 10, 11, 12,
11, 10, 9, 8, 9, 10, 11, 12, 13, 12, 12, 11, 10, 10, 11, 12,
13
};
static const uint16_t raac_hcb6_code[81] = {
0x07fe, 0x03fd, 0x01f1, 0x01eb, 0x01f4, 0x01ea, 0x01f0, 0x03fc,
0x07fd, 0x03f6, 0x01e5, 0x00ea, 0x006c, 0x0071, 0x0068, 0x00f0,
0x01e6, 0x03f7, 0x01f3, 0x00ef, 0x0032, 0x0027, 0x0028, 0x0026,
0x0031, 0x00eb, 0x01f7, 0x01e8, 0x006f, 0x002e, 0x0008, 0x0004,
0x0006, 0x0029, 0x006b, 0x01ee, 0x01ef, 0x0072, 0x002d, 0x0002,
0x0000, 0x0003, 0x002f, 0x0073, 0x01fa, 0x01e7, 0x006e, 0x002b,
0x0007, 0x0001, 0x0005, 0x002c, 0x006d, 0x01ec, 0x01f9, 0x00ee,
0x0030, 0x0024, 0x002a, 0x0025, 0x0033, 0x00ec, 0x01f2, 0x03f8,
0x01e4, 0x00ed, 0x006a, 0x0070, 0x0069, 0x0074, 0x00f1, 0x03fa,
0x07ff, 0x03f9, 0x01f6, 0x01ed, 0x01f8, 0x01e9, 0x01f5, 0x03fb,
0x07fc
};
static const uint8_t raac_hcb6_bits[81] = {
11, 10, 9, 9, 9, 9, 9, 10, 11, 10, 9, 8, 7, 7, 7, 8,
9, 10, 9, 8, 6, 6, 6, 6, 6, 8, 9, 9, 7, 6, 4, 4,
4, 6, 7, 9, 9, 7, 6, 4, 4, 4, 6, 7, 9, 9, 7, 6,
4, 4, 4, 6, 7, 9, 9, 8, 6, 6, 6, 6, 6, 8, 9, 10,
9, 8, 7, 7, 7, 7, 8, 10, 11, 10, 9, 9, 9, 9, 9, 10,
11
};
static const uint16_t raac_hcb7_code[64] = {
0x0000, 0x0005, 0x0037, 0x0074, 0x00f2, 0x01eb, 0x03ed, 0x07f7,
0x0004, 0x000c, 0x0035, 0x0071, 0x00ec, 0x00ee, 0x01ee, 0x01f5,
0x0036, 0x0034, 0x0072, 0x00ea, 0x00f1, 0x01e9, 0x01f3, 0x03f5,
0x0073, 0x0070, 0x00eb, 0x00f0, 0x01f1, 0x01f0, 0x03ec, 0x03fa,
0x00f3, 0x00ed, 0x01e8, 0x01ef, 0x03ef, 0x03f1, 0x03f9, 0x07fb,
0x01ed, 0x00ef, 0x01ea, 0x01f2, 0x03f3, 0x03f8, 0x07f9, 0x07fc,
0x03ee, 0x01ec, 0x01f4, 0x03f4, 0x03f7, 0x07f8, 0x0ffd, 0x0ffe,
0x07f6, 0x03f0, 0x03f2, 0x03f6, 0x07fa, 0x07fd, 0x0ffc, 0x0fff
};
static const uint8_t raac_hcb7_bits[64] = {
1, 3, 6, 7, 8, 9, 10, 11, 3, 4, 6, 7, 8, 8, 9, 9,
6, 6, 7, 8, 8, 9, 9, 10, 7, 7, 8, 8, 9, 9, 10, 10,
8, 8, 9, 9, 10, 10, 10, 11, 9, 8, 9, 9, 10, 10, 11, 11,
10, 9, 9, 10, 10, 11, 12, 12, 11, 10, 10, 10, 11, 11, 12, 12
};
static const uint16_t raac_hcb8_code[64] = {
0x000e, 0x0005, 0x0010, 0x0030, 0x006f, 0x00f1, 0x01fa, 0x03fe,
0x0003, 0x0000, 0x0004, 0x0012, 0x002c, 0x006a, 0x0075, 0x00f8,
0x000f, 0x0002, 0x0006, 0x0014, 0x002e, 0x0069, 0x0072, 0x00f5,
0x002f, 0x0011, 0x0013, 0x002a, 0x0032, 0x006c, 0x00ec, 0x00fa,
0x0071, 0x002b, 0x002d, 0x0031, 0x006d, 0x0070, 0x00f2, 0x01f9,
0x00ef, 0x0068, 0x0033, 0x006b, 0x006e, 0x00ee, 0x00f9, 0x03fc,
0x01f8, 0x0074, 0x0073, 0x00ed, 0x00f0, 0x00f6, 0x01f6, 0x01fd,
0x03fd, 0x00f3, 0x00f4, 0x00f7, 0x01f7, 0x01fb, 0x01fc, 0x03ff
};
static const uint8_t raac_hcb8_bits[64] = {
5, 4, 5, 6, 7, 8, 9, 10, 4, 3, 4, 5, 6, 7, 7, 8,
5, 4, 4, 5, 6, 7, 7, 8, 6, 5, 5, 6, 6, 7, 8, 8,
7, 6, 6, 6, 7, 7, 8, 9, 8, 7, 6, 7, 7, 8, 8, 10,
9, 7, 7, 8, 8, 8, 9, 9, 10, 8, 8, 8, 9, 9, 9, 10
};
static const uint16_t raac_hcb9_code[169] = {
0x0000, 0x0005, 0x0037, 0x00e7, 0x01de, 0x03ce, 0x03d9, 0x07c8,
0x07cd, 0x0fc8, 0x0fdd, 0x1fe4, 0x1fec, 0x0004, 0x000c, 0x0035,
0x0072, 0x00ea, 0x00ed, 0x01e2, 0x03d1, 0x03d3, 0x03e0, 0x07d8,
0x0fcf, 0x0fd5, 0x0036, 0x0034, 0x0071, 0x00e8, 0x00ec, 0x01e1,
0x03cf, 0x03dd, 0x03db, 0x07d0, 0x0fc7, 0x0fd4, 0x0fe4, 0x00e6,
0x0070, 0x00e9, 0x01dd, 0x01e3, 0x03d2, 0x03dc, 0x07cc, 0x07ca,
0x07de, 0x0fd8, 0x0fea, 0x1fdb, 0x01df, 0x00eb, 0x01dc, 0x01e6,
0x03d5, 0x03de, 0x07cb, 0x07dd, 0x07dc, 0x0fcd, 0x0fe2, 0x0fe7,
0x1fe1, 0x03d0, 0x01e0, 0x01e4, 0x03d6, 0x07c5, 0x07d1, 0x07db,
0x0fd2, 0x07e0, 0x0fd9, 0x0feb, 0x1fe3, 0x1fe9, 0x07c4, 0x01e5,
0x03d7, 0x07c6, 0x07cf, 0x07da, 0x0fcb, 0x0fda, 0x0fe3, 0x0fe9,
0x1fe6, 0x1ff3, 0x1ff7, 0x07d3, 0x03d8, 0x03e1, 0x07d4, 0x07d9,
0x0fd3, 0x0fde, 0x1fdd, 0x1fd9, 0x1fe2, 0x1fea, 0x1ff1, 0x1ff6,
0x07d2, 0x03d4, 0x03da, 0x07c7, 0x07d7, 0x07e2, 0x0fce, 0x0fdb,
0x1fd8, 0x1fee, 0x3ff0, 0x1ff4, 0x3ff2, 0x07e1, 0x03df, 0x07c9,
0x07d6, 0x0fca, 0x0fd0, 0x0fe5, 0x0fe6, 0x1feb, 0x1fef, 0x3ff3,
0x3ff4, 0x3ff5, 0x0fe0, 0x07ce, 0x07d5, 0x0fc6, 0x0fd1, 0x0fe1,
0x1fe0, 0x1fe8, 0x1ff0, 0x3ff1, 0x3ff8, 0x3ff6, 0x7ffc, 0x0fe8,
0x07df, 0x0fc9, 0x0fd7, 0x0fdc, 0x1fdc, 0x1fdf, 0x1fed, 0x1ff5,
0x3ff9, 0x3ffb, 0x7ffd, 0x7ffe, 0x1fe7, 0x0fcc, 0x0fd6, 0x0fdf,
0x1fde, 0x1fda, 0x1fe5, 0x1ff2, 0x3ffa, 0x3ff7, 0x3ffc, 0x3ffd,
0x7fff
};
static const uint8_t raac_hcb9_bits[169] = {
1, 3, 6, 8, 9, 10, 10, 11, 11, 12, 12, 13, 13, 3, 4, 6,
7, 8, 8, 9, 10, 10, 10, 11, 12, 12, 6, 6, 7, 8, 8, 9,
10, 10, 10, 11, 12, 12, 12, 8, 7, 8, 9, 9, 10, 10, 11, 11,
11, 12, 12, 13, 9, 8, 9, 9, 10, 10, 11, 11, 11, 12, 12, 12,
13, 10, 9, 9, 10, 11, 11, 11, 12, 11, 12, 12, 13, 13, 11, 9,
10, 11, 11, 11, 12, 12, 12, 12, 13, 13, 13, 11, 10, 10, 11, 11,
12, 12, 13, 13, 13, 13, 13, 13, 11, 10, 10, 11, 11, 11, 12, 12,
13, 13, 14, 13, 14, 11, 10, 11, 11, 12, 12, 12, 12, 13, 13, 14,
14, 14, 12, 11, 11, 12, 12, 12, 13, 13, 13, 14, 14, 14, 15, 12,
11, 12, 12, 12, 13, 13, 13, 13, 14, 14, 15, 15, 13, 12, 12, 12,
13, 13, 13, 13, 14, 14, 14, 14, 15
};
static const uint16_t raac_hcb10_code[169] = {
0x0022, 0x0008, 0x001d, 0x0026, 0x005f, 0x00d3, 0x01cf, 0x03d0,
0x03d7, 0x03ed, 0x07f0, 0x07f6, 0x0ffd, 0x0007, 0x0000, 0x0001,
0x0009, 0x0020, 0x0054, 0x0060, 0x00d5, 0x00dc, 0x01d4, 0x03cd,
0x03de, 0x07e7, 0x001c, 0x0002, 0x0006, 0x000c, 0x001e, 0x0028,
0x005b, 0x00cd, 0x00d9, 0x01ce, 0x01dc, 0x03d9, 0x03f1, 0x0025,
0x000b, 0x000a, 0x000d, 0x0024, 0x0057, 0x0061, 0x00cc, 0x00dd,
0x01cc, 0x01de, 0x03d3, 0x03e7, 0x005d, 0x0021, 0x001f, 0x0023,
0x0027, 0x0059, 0x0064, 0x00d8, 0x00df, 0x01d2, 0x01e2, 0x03dd,
0x03ee, 0x00d1, 0x0055, 0x0029, 0x0056, 0x0058, 0x0062, 0x00ce,
0x00e0, 0x00e2, 0x01da, 0x03d4, 0x03e3, 0x07eb, 0x01c9, 0x005e,
0x005a, 0x005c, 0x0063, 0x00ca, 0x00da, 0x01c7, 0x01ca, 0x01e0,
0x03db, 0x03e8, 0x07ec, 0x01e3, 0x00d2, 0x00cb, 0x00d0, 0x00d7,
0x00db, 0x01c6, 0x01d5, 0x01d8, 0x03ca, 0x03da, 0x07ea, 0x07f1,
0x01e1, 0x00d4, 0x00cf, 0x00d6, 0x00de, 0x00e1, 0x01d0, 0x01d6,
0x03d1, 0x03d5, 0x03f2, 0x07ee, 0x07fb, 0x03e9, 0x01cd, 0x01c8,
0x01cb, 0x01d1, 0x01d7, 0x01df, 0x03cf, 0x03e0, 0x03ef, 0x07e6,
0x07f8, 0x0ffa, 0x03eb, 0x01dd, 0x01d3, 0x01d9, 0x01db, 0x03d2,
0x03cc, 0x03dc, 0x03ea, 0x07ed, 0x07f3, 0x07f9, 0x0ff9, 0x07f2,
0x03ce, 0x01e4, 0x03cb, 0x03d8, 0x03d6, 0x03e2, 0x03e5, 0x07e8,
0x07f4, 0x07f5, 0x07f7, 0x0ffb, 0x07fa, 0x03ec, 0x03df, 0x03e1,
0x03e4, 0x03e6, 0x03f0, 0x07e9, 0x07ef, 0x0ff8, 0x0ffe, 0x0ffc,
0x0fff
};
static const uint8_t raac_hcb10_bits[169] = {
6, 5, 6, 6, 7, 8, 9, 10, 10, 10, 11, 11, 12, 5, 4, 4,
5, 6, 7, 7, 8, 8, 9, 10, 10, 11, 6, 4, 5, 5, 6, 6,
7, 8, 8, 9, 9, 10, 10, 6, 5, 5, 5, 6, 7, 7, 8, 8,
9, 9, 10, 10, 7, 6, 6, 6, 6, 7, 7, 8, 8, 9, 9, 10,
10, 8, 7, 6, 7, 7, 7, 8, 8, 8, 9, 10, 10, 11, 9, 7,
7, 7, 7, 8, 8, 9, 9, 9, 10, 10, 11, 9, 8, 8, 8, 8,
8, 9, 9, 9, 10, 10, 11, 11, 9, 8, 8, 8, 8, 8, 9, 9,
10, 10, 10, 11, 11, 10, 9, 9, 9, 9, 9, 9, 10, 10, 10, 11,
11, 12, 10, 9, 9, 9, 9, 10, 10, 10, 10, 11, 11, 11, 12, 11,
10, 9, 10, 10, 10, 10, 10, 11, 11, 11, 11, 12, 11, 10, 10, 10,
10, 10, 10, 11, 11, 12, 12, 12, 12
};
static const uint16_t raac_hcb11_code[289] = {
0x0000, 0x0006, 0x0019, 0x003d, 0x009c, 0x00c6, 0x01a7, 0x0390,
0x03c2, 0x03df, 0x07e6, 0x07f3, 0x0ffb, 0x07ec, 0x0ffa, 0x0ffe,
0x038e, 0x0005, 0x0001, 0x0008, 0x0014, 0x0037, 0x0042, 0x0092,
0x00af, 0x0191, 0x01a5, 0x01b5, 0x039e, 0x03c0, 0x03a2, 0x03cd,
0x07d6, 0x00ae, 0x0017, 0x0007, 0x0009, 0x0018, 0x0039, 0x0040,
0x008e, 0x00a3, 0x00b8, 0x0199, 0x01ac, 0x01c1, 0x03b1, 0x0396,
0x03be, 0x03ca, 0x009d, 0x003c, 0x0015, 0x0016, 0x001a, 0x003b,
0x0044, 0x0091, 0x00a5, 0x00be, 0x0196, 0x01ae, 0x01b9, 0x03a1,
0x0391, 0x03a5, 0x03d5, 0x0094, 0x009a, 0x0036, 0x0038, 0x003a,
0x0041, 0x008c, 0x009b, 0x00b0, 0x00c3, 0x019e, 0x01ab, 0x01bc,
0x039f, 0x038f, 0x03a9, 0x03cf, 0x0093, 0x00bf, 0x003e, 0x003f,
0x0043, 0x0045, 0x009e, 0x00a7, 0x00b9, 0x0194, 0x01a2, 0x01ba,
0x01c3, 0x03a6, 0x03a7, 0x03bb, 0x03d4, 0x009f, 0x01a0, 0x008f,
0x008d, 0x0090, 0x0098, 0x00a6, 0x00b6, 0x00c4, 0x019f, 0x01af,
0x01bf, 0x0399, 0x03bf, 0x03b4, 0x03c9, 0x03e7, 0x00a8, 0x01b6,
0x00ab, 0x00a4, 0x00aa, 0x00b2, 0x00c2, 0x00c5, 0x0198, 0x01a4,
0x01b8, 0x038c, 0x03a4, 0x03c4, 0x03c6, 0x03dd, 0x03e8, 0x00ad,
0x03af, 0x0192, 0x00bd, 0x00bc, 0x018e, 0x0197, 0x019a, 0x01a3,
0x01b1, 0x038d, 0x0398, 0x03b7, 0x03d3, 0x03d1, 0x03db, 0x07dd,
0x00b4, 0x03de, 0x01a9, 0x019b, 0x019c, 0x01a1, 0x01aa, 0x01ad,
0x01b3, 0x038b, 0x03b2, 0x03b8, 0x03ce, 0x03e1, 0x03e0, 0x07d2,
0x07e5, 0x00b7, 0x07e3, 0x01bb, 0x01a8, 0x01a6, 0x01b0, 0x01b2,
0x01b7, 0x039b, 0x039a, 0x03ba, 0x03b5, 0x03d6, 0x07d7, 0x03e4,
0x07d8, 0x07ea, 0x00ba, 0x07e8, 0x03a0, 0x01bd, 0x01b4, 0x038a,
0x01c4, 0x0392, 0x03aa, 0x03b0, 0x03bc, 0x03d7, 0x07d4, 0x07dc,
0x07db, 0x07d5, 0x07f0, 0x00c1, 0x07fb, 0x03c8, 0x03a3, 0x0395,
0x039d, 0x03ac, 0x03ae, 0x03c5, 0x03d8, 0x03e2, 0x03e6, 0x07e4,
0x07e7, 0x07e0, 0x07e9, 0x07f7, 0x0190, 0x07f2, 0x0393, 0x01be,
0x01c0, 0x0394, 0x0397, 0x03ad, 0x03c3, 0x03c1, 0x03d2, 0x07da,
0x07d9, 0x07df, 0x07eb, 0x07f4, 0x07fa, 0x0195, 0x07f8, 0x03bd,
0x039c, 0x03ab, 0x03a8, 0x03b3, 0x03b9, 0x03d0, 0x03e3, 0x03e5,
0x07e2, 0x07de, 0x07ed, 0x07f1, 0x07f9, 0x07fc, 0x0193, 0x0ffd,
0x03dc, 0x03b6, 0x03c7, 0x03cc, 0x03cb, 0x03d9, 0x03da, 0x07d3,
0x07e1, 0x07ee, 0x07ef, 0x07f5, 0x07f6, 0x0ffc, 0x0fff, 0x019d,
0x01c2, 0x00b5, 0x00a1, 0x0096, 0x0097, 0x0095, 0x0099, 0x00a0,
0x00a2, 0x00ac, 0x00a9, 0x00b1, 0x00b3, 0x00bb, 0x00c0, 0x018f,
0x0004
};
static const uint8_t raac_hcb11_bits[289] = {
4, 5, 6, 7, 8, 8, 9, 10, 10, 10, 11, 11, 12, 11, 12, 12,
10, 5, 4, 5, 6, 7, 7, 8, 8, 9, 9, 9, 10, 10, 10, 10,
11, 8, 6, 5, 5, 6, 7, 7, 8, 8, 8, 9, 9, 9, 10, 10,
10, 10, 8, 7, 6, 6, 6, 7, 7, 8, 8, 8, 9, 9, 9, 10,
10, 10, 10, 8, 8, 7, 7, 7, 7, 8, 8, 8, 8, 9, 9, 9,
10, 10, 10, 10, 8, 8, 7, 7, 7, 7, 8, 8, 8, 9, 9, 9,
9, 10, 10, 10, 10, 8, 9, 8, 8, 8, 8, 8, 8, 8, 9, 9,
9, 10, 10, 10, 10, 10, 8, 9, 8, 8, 8, 8, 8, 8, 9, 9,
9, 10, 10, 10, 10, 10, 10, 8, 10, 9, 8, 8, 9, 9, 9, 9,
9, 10, 10, 10, 10, 10, 10, 11, 8, 10, 9, 9, 9, 9, 9, 9,
9, 10, 10, 10, 10, 10, 10, 11, 11, 8, 11, 9, 9, 9, 9, 9,
9, 10, 10, 10, 10, 10, 11, 10, 11, 11, 8, 11, 10, 9, 9, 10,
9, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 8, 11, 10, 10, 10,
10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 9, 11, 10, 9,
9, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 9, 11, 10,
10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 9, 12,
10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 12, 12, 9,
9, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 9,
5
};
static const uint16_t raac_hcb_size[11] = {81,81,81,81,81,81,64,64,169,169,289};
static const uint16_t *const raac_hcb_code[11] = {
raac_hcb1_code, raac_hcb2_code, raac_hcb3_code, raac_hcb4_code, raac_hcb5_code, raac_hcb6_code, raac_hcb7_code, raac_hcb8_code, raac_hcb9_code, raac_hcb10_code, raac_hcb11_code
};
static const uint8_t *const raac_hcb_bits[11] = {
raac_hcb1_bits, raac_hcb2_bits, raac_hcb3_bits, raac_hcb4_bits, raac_hcb5_bits, raac_hcb6_bits, raac_hcb7_bits, raac_hcb8_bits, raac_hcb9_bits, raac_hcb10_bits, raac_hcb11_bits
};
static const uint32_t raac_sf_code[121] = {
0x3ffe8, 0x3ffe6, 0x3ffe7, 0x3ffe5, 0x7fff5, 0x7fff1, 0x7ffed, 0x7fff6,
0x7ffee, 0x7ffef, 0x7fff0, 0x7fffc, 0x7fffd, 0x7ffff, 0x7fffe, 0x7fff7,
0x7fff8, 0x7fffb, 0x7fff9, 0x3ffe4, 0x7fffa, 0x3ffe3, 0x1ffef, 0x1fff0,
0x0fff5, 0x1ffee, 0x0fff2, 0x0fff3, 0x0fff4, 0x0fff1, 0x07ff6, 0x07ff7,
0x03ff9, 0x03ff5, 0x03ff7, 0x03ff3, 0x03ff6, 0x03ff2, 0x01ff7, 0x01ff5,
0x00ff9, 0x00ff7, 0x00ff6, 0x007f9, 0x00ff4, 0x007f8, 0x003f9, 0x003f7,
0x003f5, 0x001f8, 0x001f7, 0x000fa, 0x000f8, 0x000f6, 0x00079, 0x0003a,
0x00038, 0x0001a, 0x0000b, 0x00004, 0x00000, 0x0000a, 0x0000c, 0x0001b,
0x00039, 0x0003b, 0x00078, 0x0007a, 0x000f7, 0x000f9, 0x001f6, 0x001f9,
0x003f4, 0x003f6, 0x003f8, 0x007f5, 0x007f4, 0x007f6, 0x007f7, 0x00ff5,
0x00ff8, 0x01ff4, 0x01ff6, 0x01ff8, 0x03ff8, 0x03ff4, 0x0fff0, 0x07ff4,
0x0fff6, 0x07ff5, 0x3ffe2, 0x7ffd9, 0x7ffda, 0x7ffdb, 0x7ffdc, 0x7ffdd,
0x7ffde, 0x7ffd8, 0x7ffd2, 0x7ffd3, 0x7ffd4, 0x7ffd5, 0x7ffd6, 0x7fff2,
0x7ffdf, 0x7ffe7, 0x7ffe8, 0x7ffe9, 0x7ffea, 0x7ffeb, 0x7ffe6, 0x7ffe0,
0x7ffe1, 0x7ffe2, 0x7ffe3, 0x7ffe4, 0x7ffe5, 0x7ffd7, 0x7ffec, 0x7fff4,
0x7fff3
};
static const uint8_t raac_sf_bits[121] = {
18, 18, 18, 18, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
19, 19, 19, 18, 19, 18, 17, 17, 16, 17, 16, 16, 16, 16, 15, 15,
14, 14, 14, 14, 14, 14, 13, 13, 12, 12, 12, 11, 12, 11, 10, 10,
10, 9, 9, 8, 8, 8, 7, 6, 6, 5, 4, 3, 1, 4, 4, 5,
6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 10, 11, 11, 11, 11, 12,
12, 13, 13, 13, 14, 14, 16, 15, 16, 15, 18, 19, 19, 19, 19, 19,
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
19, 19, 19, 19, 19, 19, 19, 19, 19
};
static const uint16_t raac_swb_offset_1024_16[44] = {
0, 8, 16, 24, 32, 40, 48, 56, 64, 72, 80, 88,
100, 112, 124, 136, 148, 160, 172, 184, 196, 212, 228, 244,
260, 280, 300, 320, 344, 368, 396, 424, 456, 492, 532, 572,
616, 664, 716, 772, 832, 896, 960, 1024
};
static const uint16_t raac_swb_offset_1024_24[48] = {
0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44,
52, 60, 68, 76, 84, 92, 100, 108, 116, 124, 136, 148,
160, 172, 188, 204, 220, 240, 260, 284, 308, 336, 364, 396,
432, 468, 508, 552, 600, 652, 704, 768, 832, 896, 960, 1024
};
static const uint16_t raac_swb_offset_1024_32[52] = {
0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 48,
56, 64, 72, 80, 88, 96, 108, 120, 132, 144, 160, 176,
196, 216, 240, 264, 292, 320, 352, 384, 416, 448, 480, 512,
544, 576, 608, 640, 672, 704, 736, 768, 800, 832, 864, 896,
928, 960, 992, 1024
};
static const uint16_t raac_swb_offset_1024_48[50] = {
0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 48,
56, 64, 72, 80, 88, 96, 108, 120, 132, 144, 160, 176,
196, 216, 240, 264, 292, 320, 352, 384, 416, 448, 480, 512,
544, 576, 608, 640, 672, 704, 736, 768, 800, 832, 864, 896,
928, 1024
};
static const uint16_t raac_swb_offset_1024_64[48] = {
0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44,
48, 52, 56, 64, 72, 80, 88, 100, 112, 124, 140, 156,
172, 192, 216, 240, 268, 304, 344, 384, 424, 464, 504, 544,
584, 624, 664, 704, 744, 784, 824, 864, 904, 944, 984, 1024
};
static const uint16_t raac_swb_offset_1024_8[41] = {
0, 12, 24, 36, 48, 60, 72, 84, 96, 108, 120, 132,
144, 156, 172, 188, 204, 220, 236, 252, 268, 288, 308, 328,
348, 372, 396, 420, 448, 476, 508, 544, 580, 620, 664, 712,
764, 820, 880, 944, 1024
};
static const uint16_t raac_swb_offset_1024_96[42] = {
0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44,
48, 52, 56, 64, 72, 80, 88, 96, 108, 120, 132, 144,
156, 172, 188, 212, 240, 276, 320, 384, 448, 512, 576, 640,
704, 768, 832, 896, 960, 1024
};
static const uint16_t *const raac_swb_offset_1024[13] = {
raac_swb_offset_1024_96, raac_swb_offset_1024_96, raac_swb_offset_1024_64,
raac_swb_offset_1024_48, raac_swb_offset_1024_48, raac_swb_offset_1024_32,
raac_swb_offset_1024_24, raac_swb_offset_1024_24, raac_swb_offset_1024_16,
raac_swb_offset_1024_16, raac_swb_offset_1024_16, raac_swb_offset_1024_8,
raac_swb_offset_1024_8
};
static const uint16_t raac_swb_offset_128_16[16] = {
0, 4, 8, 12, 16, 20, 24, 28, 32, 40, 48, 60,
72, 88, 108, 128
@@ -317,6 +693,9 @@ static const uint16_t *const raac_swb_offset_128[13] = {
raac_swb_offset_128_16, raac_swb_offset_128_16, raac_swb_offset_128_8,
raac_swb_offset_128_8
};
static const uint8_t raac_num_swb_1024[13] = {
41, 41, 47, 49, 49, 51, 47, 47, 43, 43, 43, 40, 40
};
static const uint8_t raac_num_swb_128[13] = {
12, 12, 12, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15
};
@@ -330,6 +709,10 @@ static const uint8_t raac_tns_max_bands_128[13] = {
9, 9, 10, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14
};
static const unsigned raac_sample_rates[13] = {
96000, 88200, 64000, 48000, 44100, 32000,
24000, 22050, 16000, 12000, 11025, 8000, 7350
};
/* ===== bit reader (MSB first) ===== */
-684
View File
@@ -1,684 +0,0 @@
/* Copyright (C) 2010-2026 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (raac_encode.c).
* ---------------------------------------------------------------------------------------
*
* Permission is hereby granted, free of charge,
* to any person obtaining a copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/* AAC-LC encoder. See raac_encode.h. Written from ISO/IEC 14496-3,
* subpart 4, its tables shared with raac (raac_tables.h).
*
* The MDCT is a DCT-IV of the folded window, by a complex FFT of a
* quarter its length. A band's scalefactor is sf = B + 2 log2(rms),
* its step growing with the square root of the band's level: halfway
* between the same noise in every band (the most signal-to-noise ratio
* overall) and the same ratio in every band (quiet bands kept as well
* as loud). B, one number a frame, is searched for the frame's bits;
* no step is finer than 60 dB under the frame's loudest band. */
#include <math.h>
#include <stdlib.h>
#include <string.h>
#include <formats/raac_encode.h>
#include "raac_tables.h"
#define N 2048
#define M 1024
#define MAX_SFB 51
#ifndef M_PI
#define M_PI 3.14159265358979323846
#endif
typedef struct
{
float re, im;
} cplx_t;
typedef struct
{
float prev[M]; /* the last frame's samples */
float spec[M]; /* this frame's MDCT */
int q[M]; /* its quantised values */
int sf[MAX_SFB];
uint8_t cb[MAX_SFB];
int sf_floor; /* the frame's finest scalefactor */
} enc_channel_t;
struct raac_encoder
{
raac_encoder_config_t cfg;
unsigned sfi;
unsigned num_swb, max_sfb;
const uint16_t *swb;
int debt; /* bits over the rate so far */
int last_b; /* the last frame's B, where the search starts */
bool flushed;
float window[N];
cplx_t twiddle[M / 4]; /* the FFT's */
cplx_t pre[M / 2], post[M / 2];
uint16_t bitrev[M / 2];
enc_channel_t ch[2];
/* scratch */
float x[N];
cplx_t z[M / 2];
/* output */
uint8_t *out;
size_t cap, pos;
uint32_t acc;
unsigned nbits;
bool overflow;
};
/* --------------------------------------------------------------------- */
/* Transform */
/* --------------------------------------------------------------------- */
/* In place, radix 2, M/2 points */
static void fft(raac_encoder_t *e, cplx_t *z)
{
unsigned n = M / 2, i, len;
for (i = 0; i < n; i++)
{
unsigned j = e->bitrev[i];
if (j > i)
{
cplx_t t = z[i];
z[i] = z[j];
z[j] = t;
}
}
for (len = 2; len <= n; len <<= 1)
{
unsigned half = len / 2, step = n / len, k;
for (i = 0; i < n; i += len)
for (k = 0; k < half; k++)
{
cplx_t w = e->twiddle[k * step];
cplx_t a = z[i + k], b = z[i + k + half], t;
t.re = b.re * w.re - b.im * w.im;
t.im = b.re * w.im + b.im * w.re;
z[i + k].re = a.re + t.re;
z[i + k].im = a.im + t.im;
z[i + k + half].re = a.re - t.re;
z[i + k + half].im = a.im - t.im;
}
}
}
/* The MDCT of N windowed samples into M coefficients:
* X[k] = 2 sum x[n] cos(2 pi / N (n + 1/2 + N/4)(k + 1/2)) */
/* sample @k of the fold, (-c_r - d, a - b_r) of the window's quarters */
static float fold(const float *x, unsigned k)
{
return k < M / 2 ? -x[3 * M / 2 - 1 - k] - x[3 * M / 2 + k]
: x[k - M / 2] - x[3 * M / 2 - 1 - k];
}
static void mdct(raac_encoder_t *e, const float *x, float *out)
{
unsigned i;
/* the DCT-IV of the fold by an M/2 point FFT, folded straight into
* its input */
for (i = 0; i < M / 2; i++)
{
float a = fold(x, 2 * i), b = fold(x, M - 1 - 2 * i);
e->z[i].re = a * e->pre[i].re - b * e->pre[i].im;
e->z[i].im = a * e->pre[i].im + b * e->pre[i].re;
}
fft(e, e->z);
for (i = 0; i < M / 2; i++)
{
float re = e->z[i].re * e->post[i].re - e->z[i].im * e->post[i].im;
float im = e->z[i].re * e->post[i].im + e->z[i].im * e->post[i].re;
out[2 * i] = 2.0f * re;
out[M - 1 - 2 * i] = -2.0f * im;
}
}
/* --------------------------------------------------------------------- */
/* Setup */
/* --------------------------------------------------------------------- */
raac_encoder_t *raac_encoder_new(const raac_encoder_config_t *c)
{
raac_encoder_t *e;
unsigned i, bits, cutoff, per_ch;
if (!c || (c->channels != 1 && c->channels != 2) || !c->bitrate)
return NULL;
for (i = 0; i < 13; i++)
if (raac_sample_rates[i] == c->sample_rate)
break;
if (i == 13)
return NULL;
if (!(e = (raac_encoder_t*)calloc(1, sizeof(*e))))
return NULL;
e->cfg = *c;
e->sfi = i;
e->num_swb = raac_num_swb_1024[i];
e->swb = raac_swb_offset_1024[i];
/* the bandwidth the rate allows a channel */
per_ch = c->bitrate / c->channels;
cutoff = per_ch >= 96000 ? 20000 : per_ch >= 64000 ? 16000
: per_ch >= 48000 ? 13000 : per_ch >= 32000 ? 10000 : 7000;
if (cutoff > c->sample_rate / 2)
cutoff = c->sample_rate / 2;
for (e->max_sfb = 0; e->max_sfb < e->num_swb; e->max_sfb++)
if ((unsigned)e->swb[e->max_sfb] * c->sample_rate / (2 * M) >= cutoff)
break;
if (!e->max_sfb)
e->max_sfb = 1;
e->last_b = 60;
for (i = 0; i < N; i++)
e->window[i] = (float)sin(M_PI * (i + 0.5) / N);
for (i = 0; i < M / 4; i++)
{
e->twiddle[i].re = (float)cos(-2.0 * M_PI * i / (M / 2));
e->twiddle[i].im = (float)sin(-2.0 * M_PI * i / (M / 2));
}
for (i = 0; i < M / 2; i++)
{
unsigned r = 0, k;
for (k = 0, bits = i; k < 9; k++, bits >>= 1)
r = (r << 1) | (bits & 1);
e->bitrev[i] = (uint16_t)r;
e->pre[i].re = (float)cos(-M_PI * (i + 0.25) / M);
e->pre[i].im = (float)sin(-M_PI * (i + 0.25) / M);
e->post[i].re = (float)cos(-M_PI * i / M);
e->post[i].im = (float)sin(-M_PI * i / M);
}
return e;
}
void raac_encoder_free(raac_encoder_t *e)
{
free(e);
}
size_t raac_encoder_asc(const raac_encoder_t *e, uint8_t *dst, size_t cap)
{
if (!e || !dst || cap < 2)
return 0;
/* AAC LC (2), the rate's index, the channels; 1024-sample frames,
* no core coder, no extension */
dst[0] = (uint8_t)((2 << 3) | (e->sfi >> 1));
dst[1] = (uint8_t)(((e->sfi & 1) << 7) | (e->cfg.channels << 3));
return 2;
}
/* --------------------------------------------------------------------- */
/* Bits */
/* --------------------------------------------------------------------- */
static void put_bits(raac_encoder_t *e, uint32_t v, unsigned n)
{
while (n)
{
unsigned k = n > 24 ? 24 : n;
uint32_t part = (v >> (n - k)) & ((1u << k) - 1);
e->acc = (e->acc << k) | part;
e->nbits += k;
n -= k;
while (e->nbits >= 8)
{
e->nbits -= 8;
if (e->pos < e->cap)
e->out[e->pos++] = (uint8_t)(e->acc >> e->nbits);
else
e->overflow = true;
}
}
}
/* --------------------------------------------------------------------- */
/* Quantisation and codebooks */
/* --------------------------------------------------------------------- */
#define BIG 0x3FFFFFFF
static const uint8_t book_lav[12] = { 0, 1, 1, 2, 2, 4, 4, 7, 7, 12, 12, 16 };
/* A value's escape, for codebook 11: n ones, a zero, n + 4 bits */
static unsigned esc_bits(int v)
{
unsigned n = 0;
if (v < 16)
return 0;
while ((unsigned)v >= (32u << n))
n++;
return 2 * n + 5;
}
/* Bits (or BIG) for a band's values in a codebook; with @put, codes them */
static unsigned book_bits(raac_encoder_t *e, const int *q, unsigned w,
unsigned cb, bool put)
{
const uint16_t *code = raac_hcb_code[cb - 1];
const uint8_t *len = raac_hcb_bits[cb - 1];
unsigned bits = 0, i;
bool sign = cb == 3 || cb == 4 || cb >= 7;
if (cb <= 4)
{
for (i = 0; i < w; i += 4)
{
int a[4], k, idx = 0;
for (k = 0; k < 4; k++)
{
a[k] = q[i + k];
if (abs(a[k]) > book_lav[cb])
return BIG;
idx = idx * 3 + (sign ? abs(a[k]) : a[k] + 1);
}
bits += len[idx];
if (put)
put_bits(e, code[idx], len[idx]);
if (sign)
for (k = 0; k < 4; k++)
if (a[k])
{
bits++;
if (put)
put_bits(e, a[k] < 0, 1);
}
}
return bits;
}
for (i = 0; i < w; i += 2)
{
int y = q[i], z = q[i + 1], idx, k, ay = abs(y), az = abs(z);
if (cb <= 6)
{
if (ay > 4 || az > 4)
return BIG;
idx = 9 * (y + 4) + (z + 4);
}
else if (cb <= 10)
{
unsigned lav = cb <= 8 ? 8 : 13;
if ((unsigned)ay >= lav || (unsigned)az >= lav)
return BIG;
idx = (int)lav * ay + az;
}
else
idx = 17 * (ay > 16 ? 16 : ay) + (az > 16 ? 16 : az);
bits += len[idx];
if (put)
put_bits(e, code[idx], len[idx]);
if (sign)
for (k = 0; k < 2; k++)
{
int v = k ? z : y;
if (v)
{
bits++;
if (put)
put_bits(e, v < 0, 1);
}
}
if (cb == 11)
for (k = 0; k < 2; k++)
{
int v = k ? az : ay;
unsigned eb = esc_bits(v);
bits += eb;
if (put && eb)
{
unsigned n = (eb - 5) / 2;
put_bits(e, (1u << (n + 1)) - 2, n + 1); /* n ones, a zero */
put_bits(e, (uint32_t)v - (16u << n), n + 4);
}
}
}
return bits;
}
/* The codebook that codes a band in the fewest bits; 0 if it is zero */
static unsigned pick_book(raac_encoder_t *e, const int *q, unsigned w, unsigned *bits)
{
int m = 0;
unsigned i, first, best = 0, best_bits = BIG, cb;
for (i = 0; i < w; i++)
if (abs(q[i]) > m)
m = abs(q[i]);
if (!m)
{
*bits = 0;
return 0;
}
first = m <= 1 ? 1 : m <= 2 ? 3 : m <= 4 ? 5 : m <= 7 ? 7 : m <= 12 ? 9 : 11;
for (cb = first; cb <= 11 && cb < first + 4; cb++)
{
unsigned b = book_bits(e, q, w, cb, false);
if (b < best_bits)
{
best_bits = b;
best = cb;
}
}
*bits = best_bits;
return best;
}
/* The channel quantised at B: scalefactors, values, codebooks; returns
* the bits its section, scalefactor and spectral data take */
static unsigned quantise(raac_encoder_t *e, enc_channel_t *c, int B)
{
unsigned b, bits = 0;
int prev = -1;
for (b = 0; b < e->max_sfb; b++)
{
unsigned s0 = e->swb[b], w = e->swb[b + 1] - s0, i, bb;
double en = 0, mx = 0, gain;
int sf;
for (i = 0; i < w; i++)
{
double v = fabs(c->spec[s0 + i]);
en += v * v;
if (v > mx)
mx = v;
}
if (mx < 1.0)
{
for (i = 0; i < w; i++)
c->q[s0 + i] = 0;
c->cb[b] = 0;
continue;
}
sf = (int)floor(B + 2.0 * log(sqrt(en / w)) / log(2.0) + 0.5);
/* no finer than the frame's floor: what lies that far under its
* loudest band, or under the quietest 16-bit signal, is not heard */
if (sf < c->sf_floor)
sf = c->sf_floor;
/* no value past 8191 */
{
int lo = (int)ceil(100 + 16.0 / 3.0 * (0.75 * log(mx) / log(2.0) - log(8191.0) / log(2.0)));
if (sf < lo)
sf = lo;
}
if (prev >= 0)
{
if (sf < prev - 60)
sf = prev - 60;
if (sf > prev + 60)
sf = prev + 60;
}
if (sf < 0)
sf = 0;
if (sf > 255)
sf = 255;
gain = pow(2.0, -0.1875 * (sf - 100));
for (i = 0; i < w; i++)
{
float v = c->spec[s0 + i];
int l = (int)(pow(fabs(v), 0.75) * gain + 0.4054);
if (l > 8191)
l = 8191;
c->q[s0 + i] = v < 0 ? -l : l;
}
c->cb[b] = (uint8_t)pick_book(e, c->q + s0, w, &bb);
c->sf[b] = sf;
if (!c->cb[b])
continue;
bits += bb;
/* the scalefactor's delta */
bits += raac_sf_bits[(prev < 0 ? 0 : sf - prev) + 60];
prev = sf;
}
/* sections: a codebook, then its run in 5-bit pieces */
for (b = 0; b < e->max_sfb; b++)
{
unsigned run = 1;
while (b + 1 < e->max_sfb && c->cb[b + 1] == c->cb[b])
{
b++;
run++;
}
bits += 4 + 5 * (run / 31 + 1);
}
return bits;
}
static void write_ics_info(raac_encoder_t *e)
{
put_bits(e, 0, 1); /* ics_reserved_bit */
put_bits(e, 0, 2); /* ONLY_LONG_SEQUENCE */
put_bits(e, 0, 1); /* sine window */
put_bits(e, e->max_sfb, 6);
put_bits(e, 0, 1); /* no prediction */
}
/* individual_channel_stream(): global_gain, ics_info unless a channel
* pair's common window gave it, sections, scalefactors, no pulse, TNS
* or gain control, the spectrum */
static void write_ics(raac_encoder_t *e, enc_channel_t *c, bool info)
{
unsigned b, global = 100;
int prev = -1;
for (b = 0; b < e->max_sfb; b++)
if (c->cb[b])
{
global = (unsigned)c->sf[b];
break;
}
put_bits(e, global, 8);
if (info)
write_ics_info(e);
for (b = 0; b < e->max_sfb; b++)
{
unsigned run = 1, cb = c->cb[b];
while (b + 1 < e->max_sfb && c->cb[b + 1] == cb)
{
b++;
run++;
}
put_bits(e, cb, 4);
while (run >= 31)
{
put_bits(e, 31, 5);
run -= 31;
}
put_bits(e, run, 5);
}
for (b = 0; b < e->max_sfb; b++)
{
int d;
if (!c->cb[b])
continue;
d = prev < 0 ? 0 : c->sf[b] - prev;
put_bits(e, raac_sf_code[d + 60], raac_sf_bits[d + 60]);
prev = c->sf[b];
}
put_bits(e, 0, 3); /* pulse, tns, gain control */
for (b = 0; b < e->max_sfb; b++)
if (c->cb[b])
{
unsigned s0 = e->swb[b];
book_bits(e, c->q + s0, e->swb[b + 1] - s0, c->cb[b], true);
}
}
/* --------------------------------------------------------------------- */
static size_t encode(raac_encoder_t *e, const int16_t *s16, const float *f32,
uint8_t *dst, size_t cap, bool adts)
{
unsigned ch, i, n = e->cfg.channels;
unsigned header = adts ? 7 : 0;
int target, share, lo, hi, best_b, limit;
unsigned bits_fixed = n == 1 ? 3 + 4 + 11 + 8 + 3 + 3
: 3 + 4 + 1 + 11 + 2 + 2 * (8 + 3) + 3;
if (!e || !dst)
return 0;
if (!s16 && !f32)
e->flushed = true;
for (ch = 0; ch < n; ch++)
{
enc_channel_t *c = &e->ch[ch];
for (i = 0; i < M; i++)
{
float cur = s16 ? (float)s16[i * n + ch]
: f32 ? f32[i * n + ch] * 32768.0f : 0.0f;
e->x[i] = c->prev[i] * e->window[i];
e->x[M + i] = cur * e->window[M + i];
c->prev[i] = cur;
}
mdct(e, e->x, c->spec);
/* the floor: a step 60 dB under the loudest band's level, and at
* least what a one-LSB sine comes to */
{
unsigned bb;
double peak = 0;
for (bb = 0; bb < e->max_sfb; bb++)
{
unsigned s0 = e->swb[bb], w = e->swb[bb + 1] - s0, k;
double en = 0;
for (k = 0; k < w; k++)
en += (double)c->spec[s0 + k] * c->spec[s0 + k];
if (en / w > peak)
peak = en / w;
}
peak = sqrt(peak) * 0.001; /* -60 dB */
if (peak < 64.0)
peak = 64.0;
c->sf_floor = (int)floor(100 + 4.0 * log(peak) / log(2.0) + 0.5);
}
}
/* the frame's bits: its share of the rate, the debt paid over eight
* frames, within AAC's 6144 bits a channel */
share = (int)((uint64_t)e->cfg.bitrate * M / e->cfg.sample_rate);
target = share - e->debt / 8;
limit = 6144 * (int)n - 8;
if (target < share / 4)
target = share / 4;
if (target > limit)
target = limit;
/* the largest B (coarsest) is never wanted; search for the smallest
* B whose bits fit */
lo = -120;
hi = 255;
best_b = hi;
{
int b0 = e->last_b;
/* bisection over B, starting where the last frame ended */
while (lo <= hi)
{
int mid = (lo + hi) / 2, total = (int)bits_fixed;
if (b0 >= lo && b0 <= hi)
{
mid = b0;
b0 = -1000;
}
for (ch = 0; ch < n; ch++)
total += (int)quantise(e, &e->ch[ch], mid);
if (total <= target)
{
best_b = mid;
hi = mid - 1;
}
else
lo = mid + 1;
}
}
e->last_b = best_b;
for (ch = 0; ch < n; ch++)
quantise(e, &e->ch[ch], best_b);
e->out = dst;
e->cap = cap;
e->pos = 0;
e->acc = 0;
e->nbits = 0;
e->overflow = false;
if (adts)
for (i = 0; i < 7; i++)
put_bits(e, 0, 8); /* filled in below */
if (n == 1)
{
put_bits(e, 0, 3); /* ID_SCE */
put_bits(e, 0, 4);
write_ics(e, &e->ch[0], true);
}
else
{
put_bits(e, 1, 3); /* ID_CPE */
put_bits(e, 0, 4);
put_bits(e, 1, 1); /* common_window */
write_ics_info(e);
put_bits(e, 0, 2); /* no M/S */
write_ics(e, &e->ch[0], false);
write_ics(e, &e->ch[1], false);
}
put_bits(e, 7, 3); /* ID_END */
if (e->nbits)
put_bits(e, 0, 8 - e->nbits);
if (e->overflow)
return 0;
if (adts)
{
size_t len = e->pos;
uint8_t *h = dst;
h[0] = 0xFF;
h[1] = 0xF1; /* MPEG-4, no CRC */
h[2] = (uint8_t)((1 << 6) | (e->sfi << 2) | (n >> 2));
h[3] = (uint8_t)(((n & 3) << 6) | ((len >> 11) & 3));
h[4] = (uint8_t)(len >> 3);
h[5] = (uint8_t)(((len & 7) << 5) | 0x1F);
h[6] = 0xFC;
}
e->debt += (int)((e->pos - header) * 8) - share;
if (e->debt > 64 * share)
e->debt = 64 * share;
if (e->debt < -64 * share)
e->debt = -64 * share;
return e->pos;
}
size_t raac_encoder_encode_s16(raac_encoder_t *e, const int16_t *pcm,
uint8_t *dst, size_t cap, bool adts)
{
return encode(e, pcm, NULL, dst, cap, adts);
}
size_t raac_encoder_encode_f32(raac_encoder_t *e, const float *pcm,
uint8_t *dst, size_t cap, bool adts)
{
return encode(e, NULL, pcm, dst, cap, adts);
}
-420
View File
@@ -1,420 +0,0 @@
/* Copyright (C) 2010-2026 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (raac_tables.h).
* ---------------------------------------------------------------------------------------
*
* Permission is hereby granted, free of charge,
* to any person obtaining a copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/* The tables of ISO/IEC 14496-3 that raac decodes with and raac_encode
* codes with: the spectral and scalefactor Huffman codebooks (Tables
* 4.A.2 to 4.A.13), the long window's scalefactor bands (Tables 4.129
* to 4.138) and the sampling frequency indices. Static data, for the two
* files that include it. */
#ifndef __LIBRETRO_SDK_FORMAT_RAAC_TABLES_H
#define __LIBRETRO_SDK_FORMAT_RAAC_TABLES_H
#include <stdint.h>
static const uint16_t raac_hcb1_code[81] = {
0x07f8, 0x01f1, 0x07fd, 0x03f5, 0x0068, 0x03f0, 0x07f7, 0x01ec,
0x07f5, 0x03f1, 0x0072, 0x03f4, 0x0074, 0x0011, 0x0076, 0x01eb,
0x006c, 0x03f6, 0x07fc, 0x01e1, 0x07f1, 0x01f0, 0x0061, 0x01f6,
0x07f2, 0x01ea, 0x07fb, 0x01f2, 0x0069, 0x01ed, 0x0077, 0x0017,
0x006f, 0x01e6, 0x0064, 0x01e5, 0x0067, 0x0015, 0x0062, 0x0012,
0x0000, 0x0014, 0x0065, 0x0016, 0x006d, 0x01e9, 0x0063, 0x01e4,
0x006b, 0x0013, 0x0071, 0x01e3, 0x0070, 0x01f3, 0x07fe, 0x01e7,
0x07f3, 0x01ef, 0x0060, 0x01ee, 0x07f0, 0x01e2, 0x07fa, 0x03f3,
0x006a, 0x01e8, 0x0075, 0x0010, 0x0073, 0x01f4, 0x006e, 0x03f7,
0x07f6, 0x01e0, 0x07f9, 0x03f2, 0x0066, 0x01f5, 0x07ff, 0x01f7,
0x07f4
};
static const uint8_t raac_hcb1_bits[81] = {
11, 9, 11, 10, 7, 10, 11, 9, 11, 10, 7, 10, 7, 5, 7, 9,
7, 10, 11, 9, 11, 9, 7, 9, 11, 9, 11, 9, 7, 9, 7, 5,
7, 9, 7, 9, 7, 5, 7, 5, 1, 5, 7, 5, 7, 9, 7, 9,
7, 5, 7, 9, 7, 9, 11, 9, 11, 9, 7, 9, 11, 9, 11, 10,
7, 9, 7, 5, 7, 9, 7, 10, 11, 9, 11, 10, 7, 9, 11, 9,
11
};
static const uint16_t raac_hcb2_code[81] = {
0x01f3, 0x006f, 0x01fd, 0x00eb, 0x0023, 0x00ea, 0x01f7, 0x00e8,
0x01fa, 0x00f2, 0x002d, 0x0070, 0x0020, 0x0006, 0x002b, 0x006e,
0x0028, 0x00e9, 0x01f9, 0x0066, 0x00f8, 0x00e7, 0x001b, 0x00f1,
0x01f4, 0x006b, 0x01f5, 0x00ec, 0x002a, 0x006c, 0x002c, 0x000a,
0x0027, 0x0067, 0x001a, 0x00f5, 0x0024, 0x0008, 0x001f, 0x0009,
0x0000, 0x0007, 0x001d, 0x000b, 0x0030, 0x00ef, 0x001c, 0x0064,
0x001e, 0x000c, 0x0029, 0x00f3, 0x002f, 0x00f0, 0x01fc, 0x0071,
0x01f2, 0x00f4, 0x0021, 0x00e6, 0x00f7, 0x0068, 0x01f8, 0x00ee,
0x0022, 0x0065, 0x0031, 0x0002, 0x0026, 0x00ed, 0x0025, 0x006a,
0x01fb, 0x0072, 0x01fe, 0x0069, 0x002e, 0x00f6, 0x01ff, 0x006d,
0x01f6
};
static const uint8_t raac_hcb2_bits[81] = {
9, 7, 9, 8, 6, 8, 9, 8, 9, 8, 6, 7, 6, 5, 6, 7,
6, 8, 9, 7, 8, 8, 6, 8, 9, 7, 9, 8, 6, 7, 6, 5,
6, 7, 6, 8, 6, 5, 6, 5, 3, 5, 6, 5, 6, 8, 6, 7,
6, 5, 6, 8, 6, 8, 9, 7, 9, 8, 6, 8, 8, 7, 9, 8,
6, 7, 6, 4, 6, 8, 6, 7, 9, 7, 9, 7, 6, 8, 9, 7,
9
};
static const uint16_t raac_hcb3_code[81] = {
0x0000, 0x0009, 0x00ef, 0x000b, 0x0019, 0x00f0, 0x01eb, 0x01e6,
0x03f2, 0x000a, 0x0035, 0x01ef, 0x0034, 0x0037, 0x01e9, 0x01ed,
0x01e7, 0x03f3, 0x01ee, 0x03ed, 0x1ffa, 0x01ec, 0x01f2, 0x07f9,
0x07f8, 0x03f8, 0x0ff8, 0x0008, 0x0038, 0x03f6, 0x0036, 0x0075,
0x03f1, 0x03eb, 0x03ec, 0x0ff4, 0x0018, 0x0076, 0x07f4, 0x0039,
0x0074, 0x03ef, 0x01f3, 0x01f4, 0x07f6, 0x01e8, 0x03ea, 0x1ffc,
0x00f2, 0x01f1, 0x0ffb, 0x03f5, 0x07f3, 0x0ffc, 0x00ee, 0x03f7,
0x7ffe, 0x01f0, 0x07f5, 0x7ffd, 0x1ffb, 0x3ffa, 0xffff, 0x00f1,
0x03f0, 0x3ffc, 0x01ea, 0x03ee, 0x3ffb, 0x0ff6, 0x0ffa, 0x7ffc,
0x07f2, 0x0ff5, 0xfffe, 0x03f4, 0x07f7, 0x7ffb, 0x0ff7, 0x0ff9,
0x7ffa
};
static const uint8_t raac_hcb3_bits[81] = {
1, 4, 8, 4, 5, 8, 9, 9, 10, 4, 6, 9, 6, 6, 9, 9,
9, 10, 9, 10, 13, 9, 9, 11, 11, 10, 12, 4, 6, 10, 6, 7,
10, 10, 10, 12, 5, 7, 11, 6, 7, 10, 9, 9, 11, 9, 10, 13,
8, 9, 12, 10, 11, 12, 8, 10, 15, 9, 11, 15, 13, 14, 16, 8,
10, 14, 9, 10, 14, 12, 12, 15, 11, 12, 16, 10, 11, 15, 12, 12,
15
};
static const uint16_t raac_hcb4_code[81] = {
0x0007, 0x0016, 0x00f6, 0x0018, 0x0008, 0x00ef, 0x01ef, 0x00f3,
0x07f8, 0x0019, 0x0017, 0x00ed, 0x0015, 0x0001, 0x00e2, 0x00f0,
0x0070, 0x03f0, 0x01ee, 0x00f1, 0x07fa, 0x00ee, 0x00e4, 0x03f2,
0x07f6, 0x03ef, 0x07fd, 0x0005, 0x0014, 0x00f2, 0x0009, 0x0004,
0x00e5, 0x00f4, 0x00e8, 0x03f4, 0x0006, 0x0002, 0x00e7, 0x0003,
0x0000, 0x006b, 0x00e3, 0x0069, 0x01f3, 0x00eb, 0x00e6, 0x03f6,
0x006e, 0x006a, 0x01f4, 0x03ec, 0x01f0, 0x03f9, 0x00f5, 0x00ec,
0x07fb, 0x00ea, 0x006f, 0x03f7, 0x07f9, 0x03f3, 0x0fff, 0x00e9,
0x006d, 0x03f8, 0x006c, 0x0068, 0x01f5, 0x03ee, 0x01f2, 0x07f4,
0x07f7, 0x03f1, 0x0ffe, 0x03ed, 0x01f1, 0x07f5, 0x07fe, 0x03f5,
0x07fc
};
static const uint8_t raac_hcb4_bits[81] = {
4, 5, 8, 5, 4, 8, 9, 8, 11, 5, 5, 8, 5, 4, 8, 8,
7, 10, 9, 8, 11, 8, 8, 10, 11, 10, 11, 4, 5, 8, 4, 4,
8, 8, 8, 10, 4, 4, 8, 4, 4, 7, 8, 7, 9, 8, 8, 10,
7, 7, 9, 10, 9, 10, 8, 8, 11, 8, 7, 10, 11, 10, 12, 8,
7, 10, 7, 7, 9, 10, 9, 11, 11, 10, 12, 10, 9, 11, 11, 10,
11
};
static const uint16_t raac_hcb5_code[81] = {
0x1fff, 0x0ff7, 0x07f4, 0x07e8, 0x03f1, 0x07ee, 0x07f9, 0x0ff8,
0x1ffd, 0x0ffd, 0x07f1, 0x03e8, 0x01e8, 0x00f0, 0x01ec, 0x03ee,
0x07f2, 0x0ffa, 0x0ff4, 0x03ef, 0x01f2, 0x00e8, 0x0070, 0x00ec,
0x01f0, 0x03ea, 0x07f3, 0x07eb, 0x01eb, 0x00ea, 0x001a, 0x0008,
0x0019, 0x00ee, 0x01ef, 0x07ed, 0x03f0, 0x00f2, 0x0073, 0x000b,
0x0000, 0x000a, 0x0071, 0x00f3, 0x07e9, 0x07ef, 0x01ee, 0x00ef,
0x0018, 0x0009, 0x001b, 0x00eb, 0x01e9, 0x07ec, 0x07f6, 0x03eb,
0x01f3, 0x00ed, 0x0072, 0x00e9, 0x01f1, 0x03ed, 0x07f7, 0x0ff6,
0x07f0, 0x03e9, 0x01ed, 0x00f1, 0x01ea, 0x03ec, 0x07f8, 0x0ff9,
0x1ffc, 0x0ffc, 0x0ff5, 0x07ea, 0x03f3, 0x03f2, 0x07f5, 0x0ffb,
0x1ffe
};
static const uint8_t raac_hcb5_bits[81] = {
13, 12, 11, 11, 10, 11, 11, 12, 13, 12, 11, 10, 9, 8, 9, 10,
11, 12, 12, 10, 9, 8, 7, 8, 9, 10, 11, 11, 9, 8, 5, 4,
5, 8, 9, 11, 10, 8, 7, 4, 1, 4, 7, 8, 11, 11, 9, 8,
5, 4, 5, 8, 9, 11, 11, 10, 9, 8, 7, 8, 9, 10, 11, 12,
11, 10, 9, 8, 9, 10, 11, 12, 13, 12, 12, 11, 10, 10, 11, 12,
13
};
static const uint16_t raac_hcb6_code[81] = {
0x07fe, 0x03fd, 0x01f1, 0x01eb, 0x01f4, 0x01ea, 0x01f0, 0x03fc,
0x07fd, 0x03f6, 0x01e5, 0x00ea, 0x006c, 0x0071, 0x0068, 0x00f0,
0x01e6, 0x03f7, 0x01f3, 0x00ef, 0x0032, 0x0027, 0x0028, 0x0026,
0x0031, 0x00eb, 0x01f7, 0x01e8, 0x006f, 0x002e, 0x0008, 0x0004,
0x0006, 0x0029, 0x006b, 0x01ee, 0x01ef, 0x0072, 0x002d, 0x0002,
0x0000, 0x0003, 0x002f, 0x0073, 0x01fa, 0x01e7, 0x006e, 0x002b,
0x0007, 0x0001, 0x0005, 0x002c, 0x006d, 0x01ec, 0x01f9, 0x00ee,
0x0030, 0x0024, 0x002a, 0x0025, 0x0033, 0x00ec, 0x01f2, 0x03f8,
0x01e4, 0x00ed, 0x006a, 0x0070, 0x0069, 0x0074, 0x00f1, 0x03fa,
0x07ff, 0x03f9, 0x01f6, 0x01ed, 0x01f8, 0x01e9, 0x01f5, 0x03fb,
0x07fc
};
static const uint8_t raac_hcb6_bits[81] = {
11, 10, 9, 9, 9, 9, 9, 10, 11, 10, 9, 8, 7, 7, 7, 8,
9, 10, 9, 8, 6, 6, 6, 6, 6, 8, 9, 9, 7, 6, 4, 4,
4, 6, 7, 9, 9, 7, 6, 4, 4, 4, 6, 7, 9, 9, 7, 6,
4, 4, 4, 6, 7, 9, 9, 8, 6, 6, 6, 6, 6, 8, 9, 10,
9, 8, 7, 7, 7, 7, 8, 10, 11, 10, 9, 9, 9, 9, 9, 10,
11
};
static const uint16_t raac_hcb7_code[64] = {
0x0000, 0x0005, 0x0037, 0x0074, 0x00f2, 0x01eb, 0x03ed, 0x07f7,
0x0004, 0x000c, 0x0035, 0x0071, 0x00ec, 0x00ee, 0x01ee, 0x01f5,
0x0036, 0x0034, 0x0072, 0x00ea, 0x00f1, 0x01e9, 0x01f3, 0x03f5,
0x0073, 0x0070, 0x00eb, 0x00f0, 0x01f1, 0x01f0, 0x03ec, 0x03fa,
0x00f3, 0x00ed, 0x01e8, 0x01ef, 0x03ef, 0x03f1, 0x03f9, 0x07fb,
0x01ed, 0x00ef, 0x01ea, 0x01f2, 0x03f3, 0x03f8, 0x07f9, 0x07fc,
0x03ee, 0x01ec, 0x01f4, 0x03f4, 0x03f7, 0x07f8, 0x0ffd, 0x0ffe,
0x07f6, 0x03f0, 0x03f2, 0x03f6, 0x07fa, 0x07fd, 0x0ffc, 0x0fff
};
static const uint8_t raac_hcb7_bits[64] = {
1, 3, 6, 7, 8, 9, 10, 11, 3, 4, 6, 7, 8, 8, 9, 9,
6, 6, 7, 8, 8, 9, 9, 10, 7, 7, 8, 8, 9, 9, 10, 10,
8, 8, 9, 9, 10, 10, 10, 11, 9, 8, 9, 9, 10, 10, 11, 11,
10, 9, 9, 10, 10, 11, 12, 12, 11, 10, 10, 10, 11, 11, 12, 12
};
static const uint16_t raac_hcb8_code[64] = {
0x000e, 0x0005, 0x0010, 0x0030, 0x006f, 0x00f1, 0x01fa, 0x03fe,
0x0003, 0x0000, 0x0004, 0x0012, 0x002c, 0x006a, 0x0075, 0x00f8,
0x000f, 0x0002, 0x0006, 0x0014, 0x002e, 0x0069, 0x0072, 0x00f5,
0x002f, 0x0011, 0x0013, 0x002a, 0x0032, 0x006c, 0x00ec, 0x00fa,
0x0071, 0x002b, 0x002d, 0x0031, 0x006d, 0x0070, 0x00f2, 0x01f9,
0x00ef, 0x0068, 0x0033, 0x006b, 0x006e, 0x00ee, 0x00f9, 0x03fc,
0x01f8, 0x0074, 0x0073, 0x00ed, 0x00f0, 0x00f6, 0x01f6, 0x01fd,
0x03fd, 0x00f3, 0x00f4, 0x00f7, 0x01f7, 0x01fb, 0x01fc, 0x03ff
};
static const uint8_t raac_hcb8_bits[64] = {
5, 4, 5, 6, 7, 8, 9, 10, 4, 3, 4, 5, 6, 7, 7, 8,
5, 4, 4, 5, 6, 7, 7, 8, 6, 5, 5, 6, 6, 7, 8, 8,
7, 6, 6, 6, 7, 7, 8, 9, 8, 7, 6, 7, 7, 8, 8, 10,
9, 7, 7, 8, 8, 8, 9, 9, 10, 8, 8, 8, 9, 9, 9, 10
};
static const uint16_t raac_hcb9_code[169] = {
0x0000, 0x0005, 0x0037, 0x00e7, 0x01de, 0x03ce, 0x03d9, 0x07c8,
0x07cd, 0x0fc8, 0x0fdd, 0x1fe4, 0x1fec, 0x0004, 0x000c, 0x0035,
0x0072, 0x00ea, 0x00ed, 0x01e2, 0x03d1, 0x03d3, 0x03e0, 0x07d8,
0x0fcf, 0x0fd5, 0x0036, 0x0034, 0x0071, 0x00e8, 0x00ec, 0x01e1,
0x03cf, 0x03dd, 0x03db, 0x07d0, 0x0fc7, 0x0fd4, 0x0fe4, 0x00e6,
0x0070, 0x00e9, 0x01dd, 0x01e3, 0x03d2, 0x03dc, 0x07cc, 0x07ca,
0x07de, 0x0fd8, 0x0fea, 0x1fdb, 0x01df, 0x00eb, 0x01dc, 0x01e6,
0x03d5, 0x03de, 0x07cb, 0x07dd, 0x07dc, 0x0fcd, 0x0fe2, 0x0fe7,
0x1fe1, 0x03d0, 0x01e0, 0x01e4, 0x03d6, 0x07c5, 0x07d1, 0x07db,
0x0fd2, 0x07e0, 0x0fd9, 0x0feb, 0x1fe3, 0x1fe9, 0x07c4, 0x01e5,
0x03d7, 0x07c6, 0x07cf, 0x07da, 0x0fcb, 0x0fda, 0x0fe3, 0x0fe9,
0x1fe6, 0x1ff3, 0x1ff7, 0x07d3, 0x03d8, 0x03e1, 0x07d4, 0x07d9,
0x0fd3, 0x0fde, 0x1fdd, 0x1fd9, 0x1fe2, 0x1fea, 0x1ff1, 0x1ff6,
0x07d2, 0x03d4, 0x03da, 0x07c7, 0x07d7, 0x07e2, 0x0fce, 0x0fdb,
0x1fd8, 0x1fee, 0x3ff0, 0x1ff4, 0x3ff2, 0x07e1, 0x03df, 0x07c9,
0x07d6, 0x0fca, 0x0fd0, 0x0fe5, 0x0fe6, 0x1feb, 0x1fef, 0x3ff3,
0x3ff4, 0x3ff5, 0x0fe0, 0x07ce, 0x07d5, 0x0fc6, 0x0fd1, 0x0fe1,
0x1fe0, 0x1fe8, 0x1ff0, 0x3ff1, 0x3ff8, 0x3ff6, 0x7ffc, 0x0fe8,
0x07df, 0x0fc9, 0x0fd7, 0x0fdc, 0x1fdc, 0x1fdf, 0x1fed, 0x1ff5,
0x3ff9, 0x3ffb, 0x7ffd, 0x7ffe, 0x1fe7, 0x0fcc, 0x0fd6, 0x0fdf,
0x1fde, 0x1fda, 0x1fe5, 0x1ff2, 0x3ffa, 0x3ff7, 0x3ffc, 0x3ffd,
0x7fff
};
static const uint8_t raac_hcb9_bits[169] = {
1, 3, 6, 8, 9, 10, 10, 11, 11, 12, 12, 13, 13, 3, 4, 6,
7, 8, 8, 9, 10, 10, 10, 11, 12, 12, 6, 6, 7, 8, 8, 9,
10, 10, 10, 11, 12, 12, 12, 8, 7, 8, 9, 9, 10, 10, 11, 11,
11, 12, 12, 13, 9, 8, 9, 9, 10, 10, 11, 11, 11, 12, 12, 12,
13, 10, 9, 9, 10, 11, 11, 11, 12, 11, 12, 12, 13, 13, 11, 9,
10, 11, 11, 11, 12, 12, 12, 12, 13, 13, 13, 11, 10, 10, 11, 11,
12, 12, 13, 13, 13, 13, 13, 13, 11, 10, 10, 11, 11, 11, 12, 12,
13, 13, 14, 13, 14, 11, 10, 11, 11, 12, 12, 12, 12, 13, 13, 14,
14, 14, 12, 11, 11, 12, 12, 12, 13, 13, 13, 14, 14, 14, 15, 12,
11, 12, 12, 12, 13, 13, 13, 13, 14, 14, 15, 15, 13, 12, 12, 12,
13, 13, 13, 13, 14, 14, 14, 14, 15
};
static const uint16_t raac_hcb10_code[169] = {
0x0022, 0x0008, 0x001d, 0x0026, 0x005f, 0x00d3, 0x01cf, 0x03d0,
0x03d7, 0x03ed, 0x07f0, 0x07f6, 0x0ffd, 0x0007, 0x0000, 0x0001,
0x0009, 0x0020, 0x0054, 0x0060, 0x00d5, 0x00dc, 0x01d4, 0x03cd,
0x03de, 0x07e7, 0x001c, 0x0002, 0x0006, 0x000c, 0x001e, 0x0028,
0x005b, 0x00cd, 0x00d9, 0x01ce, 0x01dc, 0x03d9, 0x03f1, 0x0025,
0x000b, 0x000a, 0x000d, 0x0024, 0x0057, 0x0061, 0x00cc, 0x00dd,
0x01cc, 0x01de, 0x03d3, 0x03e7, 0x005d, 0x0021, 0x001f, 0x0023,
0x0027, 0x0059, 0x0064, 0x00d8, 0x00df, 0x01d2, 0x01e2, 0x03dd,
0x03ee, 0x00d1, 0x0055, 0x0029, 0x0056, 0x0058, 0x0062, 0x00ce,
0x00e0, 0x00e2, 0x01da, 0x03d4, 0x03e3, 0x07eb, 0x01c9, 0x005e,
0x005a, 0x005c, 0x0063, 0x00ca, 0x00da, 0x01c7, 0x01ca, 0x01e0,
0x03db, 0x03e8, 0x07ec, 0x01e3, 0x00d2, 0x00cb, 0x00d0, 0x00d7,
0x00db, 0x01c6, 0x01d5, 0x01d8, 0x03ca, 0x03da, 0x07ea, 0x07f1,
0x01e1, 0x00d4, 0x00cf, 0x00d6, 0x00de, 0x00e1, 0x01d0, 0x01d6,
0x03d1, 0x03d5, 0x03f2, 0x07ee, 0x07fb, 0x03e9, 0x01cd, 0x01c8,
0x01cb, 0x01d1, 0x01d7, 0x01df, 0x03cf, 0x03e0, 0x03ef, 0x07e6,
0x07f8, 0x0ffa, 0x03eb, 0x01dd, 0x01d3, 0x01d9, 0x01db, 0x03d2,
0x03cc, 0x03dc, 0x03ea, 0x07ed, 0x07f3, 0x07f9, 0x0ff9, 0x07f2,
0x03ce, 0x01e4, 0x03cb, 0x03d8, 0x03d6, 0x03e2, 0x03e5, 0x07e8,
0x07f4, 0x07f5, 0x07f7, 0x0ffb, 0x07fa, 0x03ec, 0x03df, 0x03e1,
0x03e4, 0x03e6, 0x03f0, 0x07e9, 0x07ef, 0x0ff8, 0x0ffe, 0x0ffc,
0x0fff
};
static const uint8_t raac_hcb10_bits[169] = {
6, 5, 6, 6, 7, 8, 9, 10, 10, 10, 11, 11, 12, 5, 4, 4,
5, 6, 7, 7, 8, 8, 9, 10, 10, 11, 6, 4, 5, 5, 6, 6,
7, 8, 8, 9, 9, 10, 10, 6, 5, 5, 5, 6, 7, 7, 8, 8,
9, 9, 10, 10, 7, 6, 6, 6, 6, 7, 7, 8, 8, 9, 9, 10,
10, 8, 7, 6, 7, 7, 7, 8, 8, 8, 9, 10, 10, 11, 9, 7,
7, 7, 7, 8, 8, 9, 9, 9, 10, 10, 11, 9, 8, 8, 8, 8,
8, 9, 9, 9, 10, 10, 11, 11, 9, 8, 8, 8, 8, 8, 9, 9,
10, 10, 10, 11, 11, 10, 9, 9, 9, 9, 9, 9, 10, 10, 10, 11,
11, 12, 10, 9, 9, 9, 9, 10, 10, 10, 10, 11, 11, 11, 12, 11,
10, 9, 10, 10, 10, 10, 10, 11, 11, 11, 11, 12, 11, 10, 10, 10,
10, 10, 10, 11, 11, 12, 12, 12, 12
};
static const uint16_t raac_hcb11_code[289] = {
0x0000, 0x0006, 0x0019, 0x003d, 0x009c, 0x00c6, 0x01a7, 0x0390,
0x03c2, 0x03df, 0x07e6, 0x07f3, 0x0ffb, 0x07ec, 0x0ffa, 0x0ffe,
0x038e, 0x0005, 0x0001, 0x0008, 0x0014, 0x0037, 0x0042, 0x0092,
0x00af, 0x0191, 0x01a5, 0x01b5, 0x039e, 0x03c0, 0x03a2, 0x03cd,
0x07d6, 0x00ae, 0x0017, 0x0007, 0x0009, 0x0018, 0x0039, 0x0040,
0x008e, 0x00a3, 0x00b8, 0x0199, 0x01ac, 0x01c1, 0x03b1, 0x0396,
0x03be, 0x03ca, 0x009d, 0x003c, 0x0015, 0x0016, 0x001a, 0x003b,
0x0044, 0x0091, 0x00a5, 0x00be, 0x0196, 0x01ae, 0x01b9, 0x03a1,
0x0391, 0x03a5, 0x03d5, 0x0094, 0x009a, 0x0036, 0x0038, 0x003a,
0x0041, 0x008c, 0x009b, 0x00b0, 0x00c3, 0x019e, 0x01ab, 0x01bc,
0x039f, 0x038f, 0x03a9, 0x03cf, 0x0093, 0x00bf, 0x003e, 0x003f,
0x0043, 0x0045, 0x009e, 0x00a7, 0x00b9, 0x0194, 0x01a2, 0x01ba,
0x01c3, 0x03a6, 0x03a7, 0x03bb, 0x03d4, 0x009f, 0x01a0, 0x008f,
0x008d, 0x0090, 0x0098, 0x00a6, 0x00b6, 0x00c4, 0x019f, 0x01af,
0x01bf, 0x0399, 0x03bf, 0x03b4, 0x03c9, 0x03e7, 0x00a8, 0x01b6,
0x00ab, 0x00a4, 0x00aa, 0x00b2, 0x00c2, 0x00c5, 0x0198, 0x01a4,
0x01b8, 0x038c, 0x03a4, 0x03c4, 0x03c6, 0x03dd, 0x03e8, 0x00ad,
0x03af, 0x0192, 0x00bd, 0x00bc, 0x018e, 0x0197, 0x019a, 0x01a3,
0x01b1, 0x038d, 0x0398, 0x03b7, 0x03d3, 0x03d1, 0x03db, 0x07dd,
0x00b4, 0x03de, 0x01a9, 0x019b, 0x019c, 0x01a1, 0x01aa, 0x01ad,
0x01b3, 0x038b, 0x03b2, 0x03b8, 0x03ce, 0x03e1, 0x03e0, 0x07d2,
0x07e5, 0x00b7, 0x07e3, 0x01bb, 0x01a8, 0x01a6, 0x01b0, 0x01b2,
0x01b7, 0x039b, 0x039a, 0x03ba, 0x03b5, 0x03d6, 0x07d7, 0x03e4,
0x07d8, 0x07ea, 0x00ba, 0x07e8, 0x03a0, 0x01bd, 0x01b4, 0x038a,
0x01c4, 0x0392, 0x03aa, 0x03b0, 0x03bc, 0x03d7, 0x07d4, 0x07dc,
0x07db, 0x07d5, 0x07f0, 0x00c1, 0x07fb, 0x03c8, 0x03a3, 0x0395,
0x039d, 0x03ac, 0x03ae, 0x03c5, 0x03d8, 0x03e2, 0x03e6, 0x07e4,
0x07e7, 0x07e0, 0x07e9, 0x07f7, 0x0190, 0x07f2, 0x0393, 0x01be,
0x01c0, 0x0394, 0x0397, 0x03ad, 0x03c3, 0x03c1, 0x03d2, 0x07da,
0x07d9, 0x07df, 0x07eb, 0x07f4, 0x07fa, 0x0195, 0x07f8, 0x03bd,
0x039c, 0x03ab, 0x03a8, 0x03b3, 0x03b9, 0x03d0, 0x03e3, 0x03e5,
0x07e2, 0x07de, 0x07ed, 0x07f1, 0x07f9, 0x07fc, 0x0193, 0x0ffd,
0x03dc, 0x03b6, 0x03c7, 0x03cc, 0x03cb, 0x03d9, 0x03da, 0x07d3,
0x07e1, 0x07ee, 0x07ef, 0x07f5, 0x07f6, 0x0ffc, 0x0fff, 0x019d,
0x01c2, 0x00b5, 0x00a1, 0x0096, 0x0097, 0x0095, 0x0099, 0x00a0,
0x00a2, 0x00ac, 0x00a9, 0x00b1, 0x00b3, 0x00bb, 0x00c0, 0x018f,
0x0004
};
static const uint8_t raac_hcb11_bits[289] = {
4, 5, 6, 7, 8, 8, 9, 10, 10, 10, 11, 11, 12, 11, 12, 12,
10, 5, 4, 5, 6, 7, 7, 8, 8, 9, 9, 9, 10, 10, 10, 10,
11, 8, 6, 5, 5, 6, 7, 7, 8, 8, 8, 9, 9, 9, 10, 10,
10, 10, 8, 7, 6, 6, 6, 7, 7, 8, 8, 8, 9, 9, 9, 10,
10, 10, 10, 8, 8, 7, 7, 7, 7, 8, 8, 8, 8, 9, 9, 9,
10, 10, 10, 10, 8, 8, 7, 7, 7, 7, 8, 8, 8, 9, 9, 9,
9, 10, 10, 10, 10, 8, 9, 8, 8, 8, 8, 8, 8, 8, 9, 9,
9, 10, 10, 10, 10, 10, 8, 9, 8, 8, 8, 8, 8, 8, 9, 9,
9, 10, 10, 10, 10, 10, 10, 8, 10, 9, 8, 8, 9, 9, 9, 9,
9, 10, 10, 10, 10, 10, 10, 11, 8, 10, 9, 9, 9, 9, 9, 9,
9, 10, 10, 10, 10, 10, 10, 11, 11, 8, 11, 9, 9, 9, 9, 9,
9, 10, 10, 10, 10, 10, 11, 10, 11, 11, 8, 11, 10, 9, 9, 10,
9, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 8, 11, 10, 10, 10,
10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 9, 11, 10, 9,
9, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 9, 11, 10,
10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 9, 12,
10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 12, 12, 9,
9, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 9,
5
};
static const uint16_t raac_hcb_size[11] = {81,81,81,81,81,81,64,64,169,169,289};
static const uint16_t *const raac_hcb_code[11] = {
raac_hcb1_code, raac_hcb2_code, raac_hcb3_code, raac_hcb4_code, raac_hcb5_code, raac_hcb6_code, raac_hcb7_code, raac_hcb8_code, raac_hcb9_code, raac_hcb10_code, raac_hcb11_code
};
static const uint8_t *const raac_hcb_bits[11] = {
raac_hcb1_bits, raac_hcb2_bits, raac_hcb3_bits, raac_hcb4_bits, raac_hcb5_bits, raac_hcb6_bits, raac_hcb7_bits, raac_hcb8_bits, raac_hcb9_bits, raac_hcb10_bits, raac_hcb11_bits
};
static const uint32_t raac_sf_code[121] = {
0x3ffe8, 0x3ffe6, 0x3ffe7, 0x3ffe5, 0x7fff5, 0x7fff1, 0x7ffed, 0x7fff6,
0x7ffee, 0x7ffef, 0x7fff0, 0x7fffc, 0x7fffd, 0x7ffff, 0x7fffe, 0x7fff7,
0x7fff8, 0x7fffb, 0x7fff9, 0x3ffe4, 0x7fffa, 0x3ffe3, 0x1ffef, 0x1fff0,
0x0fff5, 0x1ffee, 0x0fff2, 0x0fff3, 0x0fff4, 0x0fff1, 0x07ff6, 0x07ff7,
0x03ff9, 0x03ff5, 0x03ff7, 0x03ff3, 0x03ff6, 0x03ff2, 0x01ff7, 0x01ff5,
0x00ff9, 0x00ff7, 0x00ff6, 0x007f9, 0x00ff4, 0x007f8, 0x003f9, 0x003f7,
0x003f5, 0x001f8, 0x001f7, 0x000fa, 0x000f8, 0x000f6, 0x00079, 0x0003a,
0x00038, 0x0001a, 0x0000b, 0x00004, 0x00000, 0x0000a, 0x0000c, 0x0001b,
0x00039, 0x0003b, 0x00078, 0x0007a, 0x000f7, 0x000f9, 0x001f6, 0x001f9,
0x003f4, 0x003f6, 0x003f8, 0x007f5, 0x007f4, 0x007f6, 0x007f7, 0x00ff5,
0x00ff8, 0x01ff4, 0x01ff6, 0x01ff8, 0x03ff8, 0x03ff4, 0x0fff0, 0x07ff4,
0x0fff6, 0x07ff5, 0x3ffe2, 0x7ffd9, 0x7ffda, 0x7ffdb, 0x7ffdc, 0x7ffdd,
0x7ffde, 0x7ffd8, 0x7ffd2, 0x7ffd3, 0x7ffd4, 0x7ffd5, 0x7ffd6, 0x7fff2,
0x7ffdf, 0x7ffe7, 0x7ffe8, 0x7ffe9, 0x7ffea, 0x7ffeb, 0x7ffe6, 0x7ffe0,
0x7ffe1, 0x7ffe2, 0x7ffe3, 0x7ffe4, 0x7ffe5, 0x7ffd7, 0x7ffec, 0x7fff4,
0x7fff3
};
static const uint8_t raac_sf_bits[121] = {
18, 18, 18, 18, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
19, 19, 19, 18, 19, 18, 17, 17, 16, 17, 16, 16, 16, 16, 15, 15,
14, 14, 14, 14, 14, 14, 13, 13, 12, 12, 12, 11, 12, 11, 10, 10,
10, 9, 9, 8, 8, 8, 7, 6, 6, 5, 4, 3, 1, 4, 4, 5,
6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 10, 11, 11, 11, 11, 12,
12, 13, 13, 13, 14, 14, 16, 15, 16, 15, 18, 19, 19, 19, 19, 19,
19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
19, 19, 19, 19, 19, 19, 19, 19, 19
};
static const uint16_t raac_swb_offset_1024_16[44] = {
0, 8, 16, 24, 32, 40, 48, 56, 64, 72, 80, 88,
100, 112, 124, 136, 148, 160, 172, 184, 196, 212, 228, 244,
260, 280, 300, 320, 344, 368, 396, 424, 456, 492, 532, 572,
616, 664, 716, 772, 832, 896, 960, 1024
};
static const uint16_t raac_swb_offset_1024_24[48] = {
0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44,
52, 60, 68, 76, 84, 92, 100, 108, 116, 124, 136, 148,
160, 172, 188, 204, 220, 240, 260, 284, 308, 336, 364, 396,
432, 468, 508, 552, 600, 652, 704, 768, 832, 896, 960, 1024
};
static const uint16_t raac_swb_offset_1024_32[52] = {
0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 48,
56, 64, 72, 80, 88, 96, 108, 120, 132, 144, 160, 176,
196, 216, 240, 264, 292, 320, 352, 384, 416, 448, 480, 512,
544, 576, 608, 640, 672, 704, 736, 768, 800, 832, 864, 896,
928, 960, 992, 1024
};
static const uint16_t raac_swb_offset_1024_48[50] = {
0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 48,
56, 64, 72, 80, 88, 96, 108, 120, 132, 144, 160, 176,
196, 216, 240, 264, 292, 320, 352, 384, 416, 448, 480, 512,
544, 576, 608, 640, 672, 704, 736, 768, 800, 832, 864, 896,
928, 1024
};
static const uint16_t raac_swb_offset_1024_64[48] = {
0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44,
48, 52, 56, 64, 72, 80, 88, 100, 112, 124, 140, 156,
172, 192, 216, 240, 268, 304, 344, 384, 424, 464, 504, 544,
584, 624, 664, 704, 744, 784, 824, 864, 904, 944, 984, 1024
};
static const uint16_t raac_swb_offset_1024_8[41] = {
0, 12, 24, 36, 48, 60, 72, 84, 96, 108, 120, 132,
144, 156, 172, 188, 204, 220, 236, 252, 268, 288, 308, 328,
348, 372, 396, 420, 448, 476, 508, 544, 580, 620, 664, 712,
764, 820, 880, 944, 1024
};
static const uint16_t raac_swb_offset_1024_96[42] = {
0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44,
48, 52, 56, 64, 72, 80, 88, 96, 108, 120, 132, 144,
156, 172, 188, 212, 240, 276, 320, 384, 448, 512, 576, 640,
704, 768, 832, 896, 960, 1024
};
static const uint16_t *const raac_swb_offset_1024[13] = {
raac_swb_offset_1024_96, raac_swb_offset_1024_96, raac_swb_offset_1024_64,
raac_swb_offset_1024_48, raac_swb_offset_1024_48, raac_swb_offset_1024_32,
raac_swb_offset_1024_24, raac_swb_offset_1024_24, raac_swb_offset_1024_16,
raac_swb_offset_1024_16, raac_swb_offset_1024_16, raac_swb_offset_1024_8,
raac_swb_offset_1024_8
};
static const uint8_t raac_num_swb_1024[13] = {
41, 41, 47, 49, 49, 51, 47, 47, 43, 43, 43, 40, 40
};
static const unsigned raac_sample_rates[13] = {
96000, 88200, 64000, 48000, 44100, 32000,
24000, 22050, 16000, 12000, 11025, 8000, 7350
};
#endif
File diff suppressed because it is too large. Load diff
+8 -806
View File
@@ -127,12 +127,6 @@ static size_t audio_transfer_ogg_page(const uint8_t *buf, size_t size,
#ifdef HAVE_RLPCM
#include <formats/rlpcm.h>
#endif
#ifdef HAVE_RATRAC3
#include <formats/ratrac3.h>
#endif
#ifdef HAVE_RATRAC3P
#include <formats/ratrac3p.h>
#endif
#ifdef HAVE_RAAC
#include <formats/raac.h>
#ifdef HAVE_RMP4
@@ -499,8 +493,7 @@ static size_t audio_transfer_ogg_page(const uint8_t *buf, size_t size,
* audio_transfer_webm_audio_type), .ogg being ambiguous between Vorbis
* and Opus in any case. */
#if defined(HAVE_RWAV) || defined(HAVE_RAC3) || defined(HAVE_RATRAC3) \
|| defined(HAVE_RATRAC3P)
#if defined(HAVE_RWAV) || defined(HAVE_RAC3)
/* Unit-scale float (full scale +-1.0) to s16, the conversion raac
* applies at its own edge, for the arms whose float arrives at unit
* scale already (float WAV, AC-3). A float source can carry anything, including
@@ -520,12 +513,6 @@ static int16_t audio_transfer_unit_to_s16(float unit)
}
#endif
static uint32_t audio_transfer_le32(const uint8_t *p)
{
return (uint32_t)p[0] | ((uint32_t)p[1] << 8)
| ((uint32_t)p[2] << 16) | ((uint32_t)p[3] << 24);
}
/* One transfer context per codec. Each backend keeps only what it needs;
* the enum 'type' handed to every entry point selects which arm runs, the
* same switch-dispatch pattern formats/image_transfer.c uses. */
@@ -1420,337 +1407,6 @@ static int audio_transfer_ac3_read(struct audio_transfer_ac3 *a,
}
#endif
#if defined(HAVE_RATRAC3) || defined(HAVE_RATRAC3P)
/* ATRAC3 and ATRAC3plus: OpenMG files (.oma, .aa3: an optional "ea3"
* tag, then the 96-byte EA3 header naming the codec and its frame
* size) and WAVE files (.at3: format tag 270h, or FFFEh with the
* ATRAC3plus sub-format). Frames are block_align bytes, 1024 samples a
* channel for ATRAC3 and 2048 for ATRAC3plus, decoded one at a time
* into a pending block the reads drain. Encrypted OpenMG is refused.
*
* ATRAC3plus decodes in Sony's order - FL FR FC, then the back pair,
* the back centre or the side pair, and LFE last - which is put into
* the WAV shape for the count, as the AC-3 arm does: 5.1, 6.1 and 7.1
* reordered, 6.1's back pair in WAV 7's side slots (the fold treats
* them alike), and 4.0's lone back centre split into a phantom pair at
* -3 dB each, five channels out. A frame that does not parse comes out
* as silence, the decoders keeping their history. */
struct audio_transfer_atrac
{
const uint8_t *buf;
size_t buf_size;
size_t avail; /* resident prefix, 0 = all */
size_t data, data_end;
size_t pos; /* the next frame's offset */
unsigned block_align;
unsigned spf; /* samples a channel a frame */
unsigned dec_channels; /* the stream's */
unsigned channels; /* handed over, in the WAV shape */
unsigned rate;
bool plus;
bool joint;
bool identity;
bool ended;
signed char map[8]; /* output channel: the decoded one */
float gain[8];
#ifdef HAVE_RATRAC3
ratrac3_t *d3;
#endif
#ifdef HAVE_RATRAC3P
ratrac3p_t *d3p;
#endif
float *raw; /* spf * dec_channels */
float *pend; /* spf * channels */
size_t pend_n, pend_off;
uint64_t total_frames;
uint64_t frame_pos;
};
static unsigned audio_transfer_be16(const uint8_t *p)
{
return ((unsigned)p[0] << 8) | p[1];
}
/* The container: codec, frame size, rate and where the frames are */
static bool audio_transfer_atrac_parse(struct audio_transfer_atrac *a)
{
static const unsigned rates[8] = { 32000, 44100, 48000, 88200, 96000, 0, 0, 0 };
static const unsigned plus_ch[8] = { 0, 1, 2, 3, 4, 6, 7, 8 };
const uint8_t *b = a->buf;
size_t n = a->buf_size, off = 0;
if (n >= 12 && !memcmp(b, "RIFF", 4) && !memcmp(b + 8, "WAVE", 4))
{
size_t c = 12;
bool fmt = false;
while (c + 8 <= n)
{
size_t len = audio_transfer_le32(b + c + 4);
if (len > n - c - 8)
len = n - c - 8;
if (!memcmp(b + c, "fmt ", 4))
{
#ifdef HAVE_RATRAC3P
ratrac3p_info_t pi;
if (ratrac3p_parse_wave_fmt(b + c + 8, len, &pi))
{
a->plus = true; a->dec_channels = pi.channels;
a->rate = pi.sample_rate; a->block_align = pi.block_align;
fmt = true;
}
#endif
#ifdef HAVE_RATRAC3
if (!fmt)
{
ratrac3_info_t ti;
if (ratrac3_parse_wave_fmt(b + c + 8, len, &ti))
{
a->plus = false; a->dec_channels = ti.channels;
a->rate = ti.sample_rate; a->block_align = ti.block_align;
a->joint = ti.joint_stereo;
fmt = true;
}
}
#endif
if (!fmt)
return false;
}
else if (!memcmp(b + c, "data", 4) && fmt)
{
a->data = c + 8;
a->data_end = c + 8 + len;
return true;
}
c += 8 + len + (len & 1);
}
return false;
}
/* OpenMG: "ea3" tag (an ID3v2.3 tag by another name), then "EA3" */
if (n >= 10 && !memcmp(b, "ea3", 3))
off = 10 + (((size_t)(b[6] & 0x7f) << 21) | ((size_t)(b[7] & 0x7f) << 14)
| ((size_t)(b[8] & 0x7f) << 7) | (b[9] & 0x7f));
if (off > n || n - off < 96 || memcmp(b + off, "EA3", 3))
return false;
{
const uint8_t *h = b + off;
unsigned hsize = audio_transfer_be16(h + 4);
unsigned eid = audio_transfer_be16(h + 6);
unsigned codec = h[32];
uint32_t params = ((uint32_t)h[33] << 16) | ((uint32_t)h[34] << 8) | h[35];
if (eid != 0xFFFF && eid != 0xFF80)
return false; /* encrypted */
if (hsize < 96 || hsize > n - off)
return false;
a->rate = rates[(params >> 13) & 7];
switch (codec)
{
#ifdef HAVE_RATRAC3
case 0:
a->plus = false;
a->dec_channels = 2;
a->joint = ((params >> 17) & 1) != 0;
a->block_align = (unsigned)(params & 0x3FF) * 8;
break;
#endif
#ifdef HAVE_RATRAC3P
case 1:
a->plus = true;
a->dec_channels = plus_ch[(params >> 10) & 7];
a->block_align = (unsigned)(params & 0x3FF) * 8 + 8;
break;
#endif
default:
return false;
}
a->data = off + hsize;
a->data_end = n;
}
(void)plus_ch;
return a->rate && a->dec_channels && a->block_align;
}
/* the WAV shape for ATRAC3plus's channel count (see above) */
static void audio_transfer_atrac_map(struct audio_transfer_atrac *a)
{
static const signed char maps[9][8] = {
{ 0 }, { 0 }, { 0, 1 }, { 0, 1, 2 },
{ 0, 1, 2, 3, 3 }, /* FL FR FC BC: BC split */
{ 0 },
{ 0, 1, 2, 5, 3, 4 }, /* FL FR FC BL BR LFE */
{ 0, 1, 2, 6, 5, 3, 4 }, /* FL FR FC BL BR BC LFE */
{ 0, 1, 2, 7, 3, 4, 5, 6 } /* FL FR FC BL BR SL SR LFE */
};
unsigned i, n = a->dec_channels;
a->channels = n == 4 ? 5 : n;
for (i = 0; i < a->channels; i++)
{
a->map[i] = a->plus ? maps[n][i] : (signed char)i;
a->gain[i] = (a->plus && n == 4 && i >= 3) ? 0.70710678f : 1.0f;
}
a->identity = true;
for (i = 0; i < a->channels; i++)
if (a->map[i] != (signed char)i || a->gain[i] != 1.0f)
a->identity = false;
if (a->channels != n)
a->identity = false;
}
static size_t audio_transfer_atrac_end(const struct audio_transfer_atrac *a)
{
size_t end = a->data_end;
if (a->avail && a->avail < end)
end = a->avail;
return end;
}
/* Decodes the frame at pos into @fdst (floats) or @sdst (s16) in the
* WAV shape and advances pos: 1 with @frames, 0 at the end of the
* frames or the frontier */
static int audio_transfer_atrac_next_into(struct audio_transfer_atrac *a,
float *fdst, int16_t *sdst, size_t *frames)
{
size_t end = audio_transfer_atrac_end(a), i;
float *dec;
unsigned c;
int r = -1;
if (a->pos >= end || a->block_align > end - a->pos)
return 0;
dec = (a->identity && fdst) ? fdst : a->raw;
#ifdef HAVE_RATRAC3P
if (a->plus)
r = ratrac3p_decode_float(a->d3p, a->buf + a->pos, a->block_align, dec);
#endif
#ifdef HAVE_RATRAC3
if (!a->plus)
r = ratrac3_decode_float(a->d3, a->buf + a->pos, a->block_align, dec);
#endif
(void)r; /* a frame that does not parse is silence */
if (dec != fdst)
{
if (a->identity)
for (i = 0; i < (size_t)a->spf * a->channels; i++)
sdst[i] = audio_transfer_unit_to_s16(a->raw[i]);
else
for (i = 0; i < a->spf; i++)
{
const float *in = a->raw + i * a->dec_channels;
for (c = 0; c < a->channels; c++)
{
float v = in[a->map[c]] * a->gain[c];
if (fdst)
fdst[i * a->channels + c] = v;
else
sdst[i * a->channels + c] = audio_transfer_unit_to_s16(v);
}
}
}
a->pos += a->block_align;
*frames = a->spf;
return 1;
}
static int audio_transfer_atrac_read(struct audio_transfer_atrac *a,
float *out_f32, int16_t *out_s16, size_t frames, size_t *frames_out)
{
size_t produced = 0;
if (!a || !a->raw)
return AUDIO_PROCESS_ERROR;
while (produced < frames)
{
size_t take, i, n;
const float *src;
if (a->pend_off >= a->pend_n)
{
size_t got = 0;
int r;
if (a->ended)
break;
/* room for a whole frame: straight into the caller's buffer */
if (frames - produced >= a->spf)
{
r = audio_transfer_atrac_next_into(a,
out_f32 ? out_f32 + produced * a->channels : NULL,
out_f32 ? NULL : out_s16 + produced * a->channels, &got);
if (r == 1)
{
a->frame_pos += got;
produced += got;
continue;
}
}
else
{
r = audio_transfer_atrac_next_into(a, a->pend, NULL, &got);
if (r == 1)
{
a->pend_n = got;
a->pend_off = 0;
}
}
if (r == 0)
{
if (audio_transfer_atrac_end(a) >= a->data_end)
a->ended = true;
break;
}
}
take = a->pend_n - a->pend_off;
if (take > frames - produced)
take = frames - produced;
src = a->pend + a->pend_off * a->channels;
n = take * a->channels;
if (out_f32)
memcpy(out_f32 + produced * a->channels, src, n * sizeof(float));
else
for (i = 0; i < n; i++)
out_s16[produced * a->channels + i] = audio_transfer_unit_to_s16(src[i]);
a->pend_off += take;
a->frame_pos += take;
produced += take;
}
if (frames_out)
*frames_out = produced;
if (produced == 0 && a->ended)
return AUDIO_PROCESS_END;
return AUDIO_PROCESS_NEXT;
}
/* Fresh history: the frame before the target decoded and dropped, so
* the overlap is what a playthrough would have left */
static bool audio_transfer_atrac_seek_to(struct audio_transfer_atrac *a, uint64_t frame)
{
uint64_t index = frame / a->spf;
size_t got;
if (frame >= a->total_frames)
return false;
#ifdef HAVE_RATRAC3P
if (a->plus)
ratrac3p_reset(a->d3p);
#endif
#ifdef HAVE_RATRAC3
if (!a->plus)
ratrac3_reset(a->d3);
#endif
a->ended = false;
a->pend_n = a->pend_off = 0;
if (index)
{
a->pos = a->data + (size_t)(index - 1) * a->block_align;
audio_transfer_atrac_next_into(a, a->pend, NULL, &got);
}
a->pos = a->data + (size_t)index * a->block_align;
a->frame_pos = index * a->spf;
if (audio_transfer_atrac_next_into(a, a->pend, NULL, &got) == 1)
{
a->pend_n = got;
a->pend_off = (size_t)(frame - a->frame_pos);
a->frame_pos = frame;
}
return true;
}
#endif
#ifdef HAVE_RAAC
struct audio_transfer_aac
{
@@ -1921,10 +1577,6 @@ void *audio_transfer_new(enum audio_type_enum type)
case AUDIO_TYPE_AAC:
return calloc(1, sizeof(struct audio_transfer_aac));
#endif
#if defined(HAVE_RATRAC3) || defined(HAVE_RATRAC3P)
case AUDIO_TYPE_ATRAC:
return calloc(1, sizeof(struct audio_transfer_atrac));
#endif
#ifdef HAVE_RAC3
case AUDIO_TYPE_AC3:
return calloc(1, sizeof(struct audio_transfer_ac3));
@@ -2030,18 +1682,6 @@ void audio_transfer_set_buffer_ptr(void *data, enum audio_type_enum type,
break;
}
#endif
#if defined(HAVE_RATRAC3) || defined(HAVE_RATRAC3P)
case AUDIO_TYPE_ATRAC:
{
struct audio_transfer_atrac *a = (struct audio_transfer_atrac*)data;
if (a)
{
a->buf = (const uint8_t*)ptr;
a->buf_size = len;
}
break;
}
#endif
#ifdef HAVE_RAC3
case AUDIO_TYPE_AC3:
{
@@ -2747,15 +2387,6 @@ void audio_transfer_set_avail(void *data, enum audio_type_enum type,
return;
}
#endif
#if defined(HAVE_RATRAC3) || defined(HAVE_RATRAC3P)
case AUDIO_TYPE_ATRAC:
{
struct audio_transfer_atrac *a = (struct audio_transfer_atrac*)data;
if (a)
a->avail = avail;
break;
}
#endif
#ifdef HAVE_RAC3
case AUDIO_TYPE_AC3:
{
@@ -2938,228 +2569,6 @@ enum audio_type_enum audio_transfer_webm_audio_type(const void *buf,
#endif
}
/* ---- a file's arm from its bytes ------------------------------------ */
#ifdef HAVE_RMP3
/* An MPEG audio frame header's frame length (layers I to III, MPEG-1,
* 2 and 2.5), 0 when @h is not one; free format is not taken */
static size_t audio_transfer_mpa_len(const uint8_t *h)
{
static const uint16_t kbps[2][3][15] = {
{ { 0,32,64,96,128,160,192,224,256,288,320,352,384,416,448 },
{ 0,32,48,56,64,80,96,112,128,160,192,224,256,320,384 },
{ 0,32,40,48,56,64,80,96,112,128,160,192,224,256,320 } },
{ { 0,32,48,56,64,80,96,112,128,144,160,176,192,224,256 },
{ 0,8,16,24,32,40,48,56,64,80,96,112,128,144,160 },
{ 0,8,16,24,32,40,48,56,64,80,96,112,128,144,160 } }
};
static const uint16_t rates[3] = { 44100, 48000, 32000 };
unsigned ver, layer, bi, si, pad, rate, lsf;
uint32_t br;
if (h[0] != 0xFF || (h[1] & 0xE0) != 0xE0)
return 0;
ver = (h[1] >> 3) & 3; /* 0 MPEG-2.5, 1 reserved, 2 MPEG-2, 3 MPEG-1 */
layer = 4 - ((h[1] >> 1) & 3);
bi = h[2] >> 4;
si = (h[2] >> 2) & 3;
pad = (h[2] >> 1) & 1;
if (ver == 1 || layer == 4 || bi == 0 || bi == 15 || si == 3)
return 0;
lsf = ver != 3;
rate = rates[si] >> (ver == 3 ? 0 : ver == 2 ? 1 : 2);
br = (uint32_t)kbps[lsf][layer - 1][bi] * 1000;
if (layer == 1)
return (size_t)((12 * br / rate + pad) * 4);
if (layer == 3 && lsf)
return (size_t)(72 * br / rate + pad);
return (size_t)(144 * br / rate + pad);
}
#endif
/* The length of the raw-stream frame at @p of @type's syntax, 0 when
* there is none there */
static size_t audio_transfer_raw_frame(const uint8_t *p, size_t n,
enum audio_type_enum type)
{
switch (type)
{
#ifdef HAVE_RMP3
case AUDIO_TYPE_MP3:
return n >= 4 ? audio_transfer_mpa_len(p) : 0;
#endif
#ifdef HAVE_RAAC
case AUDIO_TYPE_AAC:
{
raac_adts_t h;
return raac_adts_parse(p, n, &h) == 0 ? h.frame_size : 0;
}
#endif
#ifdef HAVE_RAC3
case AUDIO_TYPE_AC3:
{
rac3_frame_info_t info;
return rac3_parse_frame_info(p, n, &info) == RAC3_OK
? info.frame_bytes : 0;
}
#endif
default:
break;
}
(void)p; (void)n;
return 0;
}
enum audio_type_enum audio_transfer_sniff_type(const void *buf, size_t len,
size_t *skip)
{
const uint8_t *b = (const uint8_t*)buf;
size_t at = 0, i;
if (skip)
*skip = 0;
if (!b)
return AUDIO_TYPE_NONE;
#if defined(HAVE_RATRAC3) || defined(HAVE_RATRAC3P)
/* OpenMG: its "ea3" tag, or the EA3 header itself; the arm reads
* both */
if (len >= 10 && (!memcmp(b, "ea3", 3) || !memcmp(b, "EA3", 3)))
return AUDIO_TYPE_ATRAC;
#endif
/* ID3v2 tags in front of a stream, each 10 bytes, a syncsafe size
* and 10 more for a footer */
while (len - at >= 10 && !memcmp(b + at, "ID3", 3) && b[at + 3] != 0xFF
&& !((b[at + 6] | b[at + 7] | b[at + 8] | b[at + 9]) & 0x80))
{
size_t tag = 10 + (((size_t)b[at + 6] << 21) | ((size_t)b[at + 7] << 14)
| ((size_t)b[at + 8] << 7) | b[at + 9]) + ((b[at + 5] & 0x10) ? 10 : 0);
if (tag > len - at)
return AUDIO_TYPE_NONE;
at += tag;
}
b += at;
len -= at;
if (skip)
*skip = at;
#ifdef HAVE_RFLAC
if (len >= 4 && !memcmp(b, "fLaC", 4))
return AUDIO_TYPE_FLAC;
#endif
if (len >= 4 && !memcmp(b, "OggS", 4))
return audio_transfer_ogg_audio_type(b, len);
if (len >= 4 && b[0] == 0x1A && b[1] == 0x45 && b[2] == 0xDF && b[3] == 0xA3)
return audio_transfer_webm_audio_type(b, len);
if (len >= 12 && !memcmp(b, "RIFF", 4))
{
size_t c = 12;
#ifdef HAVE_RWMA
if (!memcmp(b + 8, "XWMA", 4))
return AUDIO_TYPE_WMA;
#endif
if (memcmp(b + 8, "WAVE", 4))
return AUDIO_TYPE_NONE;
/* the format tag says which arm */
while (c + 8 <= len)
{
uint32_t clen = audio_transfer_le32(b + c + 4);
if (!memcmp(b + c, "fmt ", 4) && clen >= 2 && len - c - 8 >= 2)
{
unsigned tag = b[c + 8] | ((unsigned)b[c + 9] << 8);
if (tag == 0xFFFE && clen >= 26 && len - c - 8 >= 26)
tag = b[c + 32] | ((unsigned)b[c + 33] << 8);
#ifdef HAVE_RWAV
if (tag == 1 || tag == 3)
return AUDIO_TYPE_WAV;
#endif
#ifdef HAVE_RWMA
if (tag == 0x0161 || tag == 0x0162 || tag == 0x0163)
return AUDIO_TYPE_WMA;
#endif
#ifdef HAVE_RATRAC3
if (tag == 0x0270)
return AUDIO_TYPE_ATRAC;
#endif
#ifdef HAVE_RATRAC3P
{
/* the ATRAC3plus sub-format GUID */
static const uint8_t g[16] = { 0xBF,0xAA,0x23,0xE9,0x58,0xCB,0x71,0x44,
0xA1,0x19,0xFF,0xFA,0x01,0xE4,0xCE,0x62 };
if ( b[c + 8] == 0xFE && b[c + 9] == 0xFF && clen >= 40
&& len - c - 8 >= 40 && !memcmp(b + c + 32, g, 16))
return AUDIO_TYPE_ATRAC;
}
#endif
return AUDIO_TYPE_NONE;
}
if (clen > len - c - 8)
break;
c += 8 + clen + (clen & 1);
}
return AUDIO_TYPE_NONE;
}
#ifdef HAVE_RWMA
{
static const uint8_t asf[16] = { 0x30,0x26,0xB2,0x75,0x8E,0x66,0xCF,0x11,
0xA6,0xD9,0x00,0xAA,0x00,0x62,0xCE,0x6C };
if (len >= 16 && !memcmp(b, asf, 16))
return AUDIO_TYPE_WMA;
}
#endif
#if defined(HAVE_RAAC) && defined(HAVE_RMP4)
if (len >= 8 && (!memcmp(b + 4, "ftyp", 4) || !memcmp(b + 4, "moov", 4)))
return AUDIO_TYPE_AAC;
#endif
#ifdef HAVE_RMODTRACKER
if ( (len >= 17 && !memcmp(b, "Extended Module: ", 17))
|| (len >= 4 && !memcmp(b, "IMPM", 4))
|| (len >= 48 && !memcmp(b + 44, "SCRM", 4)))
return AUDIO_TYPE_MOD;
if (len >= 1084)
{
static const char tags[][5] = { "M.K.", "M!K!", "FLT4", "FLT8", "EXO4",
"EXO8", "OKTA", "OCTA", "CD81", "FA08" };
const uint8_t *t = b + 1080;
for (i = 0; i < sizeof(tags) / sizeof(tags[0]); i++)
if (!memcmp(t, tags[i], 4))
return AUDIO_TYPE_MOD;
if ( (t[0] >= '1' && t[0] <= '9' && !memcmp(t + 1, "CHN", 3))
|| (t[0] >= '1' && t[0] <= '9' && t[1] >= '0' && t[1] <= '9'
&& !memcmp(t + 2, "CH", 2)))
return AUDIO_TYPE_MOD;
}
#endif
/* Raw streams: a frame header, and another where it says the next
* one is (or the end of the file), at the start or after a little
* junk. */
{
static const enum audio_type_enum raw[3] = {
AUDIO_TYPE_AC3, AUDIO_TYPE_AAC, AUDIO_TYPE_MP3 };
size_t limit = len < 65536 ? len : 65536;
for (i = 0; i + 4 <= limit; i++)
{
unsigned k;
for (k = 0; k < 3; k++)
{
size_t f = audio_transfer_raw_frame(b + i, len - i, raw[k]);
if ( f && f <= len - i
&& (f == len - i
|| audio_transfer_raw_frame(b + i + f, len - i - f, raw[k])))
{
if (skip)
*skip = at + i;
return raw[k];
}
}
}
}
(void)i;
return AUDIO_TYPE_NONE;
}
bool audio_transfer_set_start_trim(void *data, enum audio_type_enum type,
uint64_t frames)
{
@@ -3278,22 +2687,16 @@ static int audio_transfer_mp3_gapless(const uint8_t *b, size_t len,
if (!frames)
return 0;
/* The LAME tag starts here; its delay and padding are twelve
* bits each, packed into three bytes at offset 21. Its delay is
* the encoder's; the decoder's own, 529 samples, comes on top,
* as rmp3's pull API (RMP3_DECODER_DELAY) and FFmpeg take it -
* without it the audio started 529 samples late and its last
* 529 were cut. The padding is net of it already. */
* bits each, packed into three bytes at offset 21. */
if ((size_t)(p - b) + 24 <= len)
{
delay = ((uint64_t)p[21] << 4) | (p[22] >> 4);
pad = ((uint64_t)(p[22] & 0xf) << 8) | p[23];
*out_delay = (uint64_t)spf + delay + RMP3_DECODER_DELAY;
}
else
*out_delay = (uint64_t)spf;
/* The filler frame is decoded like any other, so it is priming
* too. What is left to play is the stated audio less both
* ends. */
*out_delay = (uint64_t)spf + delay;
*out_frames = (uint64_t)frames * spf;
*out_frames = (*out_frames > delay + pad)
? *out_frames - delay - pad : 0;
@@ -4630,39 +4033,6 @@ bool audio_transfer_start(void *data, enum audio_type_enum type)
return true;
}
#endif
#if defined(HAVE_RATRAC3) || defined(HAVE_RATRAC3P)
case AUDIO_TYPE_ATRAC:
{
struct audio_transfer_atrac *a = (struct audio_transfer_atrac*)data;
if (!a || !a->buf || !audio_transfer_atrac_parse(a))
return false;
a->spf = a->plus ? 2048 : 1024;
audio_transfer_atrac_map(a);
#ifdef HAVE_RATRAC3P
if (a->plus && !(a->d3p = ratrac3p_new(a->dec_channels, a->block_align)))
return false;
#endif
#ifdef HAVE_RATRAC3
if (!a->plus && !(a->d3 = ratrac3_new(a->dec_channels, a->block_align, a->joint)))
return false;
#endif
a->raw = (float*)malloc((size_t)a->spf * a->dec_channels * sizeof(float));
a->pend = (float*)malloc((size_t)a->spf * a->channels * sizeof(float));
if (!a->raw || !a->pend)
{
free(a->raw);
free(a->pend);
a->raw = a->pend = NULL;
return false;
}
a->total_frames = (uint64_t)((a->data_end - a->data) / a->block_align) * a->spf;
a->pos = a->data;
a->pend_n = a->pend_off = 0;
a->frame_pos = 0;
a->ended = false;
return true;
}
#endif
#ifdef HAVE_RAC3
case AUDIO_TYPE_AC3:
{
@@ -4924,10 +4294,6 @@ bool audio_transfer_start(void *data, enum audio_type_enum type)
return false;
}
ac->channels = raac_channels(ac->handle);
/* the WAVE order every arm but Vorbis and Opus hands over, and
* audio_transfer_fold_q15 folds by; a layout raac has no WAVE
* map for stays in stream order */
raac_set_channel_order(ac->handle, RAAC_ORDER_WAVE);
ac->trim_left = ac->start_trim;
ac->emitted = 0;
ac->pkt_index = 0;
@@ -4994,13 +4360,6 @@ bool audio_transfer_is_valid(void *data, enum audio_type_enum type)
return op && op->handle;
}
#endif
#if defined(HAVE_RATRAC3) || defined(HAVE_RATRAC3P)
case AUDIO_TYPE_ATRAC:
{
struct audio_transfer_atrac *a = (struct audio_transfer_atrac*)data;
return a && a->raw;
}
#endif
#ifdef HAVE_RAC3
case AUDIO_TYPE_AC3:
{
@@ -5029,106 +4388,11 @@ bool audio_transfer_is_valid(void *data, enum audio_type_enum type)
return false;
}
/* ---- folding to stereo ----------------------------------------------
*
* The arms do no channel conversion: wider than stereo comes out as the
* codec orders it, and the consumer folds. Vorbis and Opus (mapping
* family 1) order the channels one way (Vorbis I 4.3.9), everything
* else - WAV, FLAC, AAC (put into this order at start), AC-3 (shaped
* into it), MP3 - the WAVEFORMATEXTENSIBLE way:
*
* Vorbis 3 L C R 4 L R RL RR 5 L C R RL RR
* 6 L C R RL RR LFE 7 L C R RL RR BC LFE
* 8 L C R RL RR SL SR LFE
* WAV 3 FL FR FC 4 FL FR BL BR 5 FL FR FC BL BR
* 6 FL FR FC LFE BL BR 7 FL FR FC LFE BC SL SR
* 8 FL FR FC LFE BL BR SL SR
*
* Folding one with the other's table is not a subtle error: on 5.1 it
* sends front-right to both sides, front-centre to the right alone,
* LFE into the mix and back-right nowhere.
*
* Coefficients are the usual ITU-R BS.775 ones: centre and surrounds
* enter both sides at -3 dB, a lone back centre at -6 dB into each, LFE
* is dropped. Not normalised: scaling by the coefficient sum would put
* 5.1 content 7.7 dB below the same material in a stereo file, which is
* a surprising thing for a file's channel count to do to its volume;
* the sum only reaches full scale when the channels are correlated.
* Q15 in int32: unity is 32768, which an int16 would wrap. */
#define AT_FOLD_UNITY 32768
#define AT_FOLD_M3DB 23170
#define AT_FOLD_M6DB 16384
static const int32_t audio_transfer_fold_vorbis[9][8][2] = {
{ {0,0} },
{ {AT_FOLD_UNITY,AT_FOLD_UNITY} },
{ {AT_FOLD_UNITY,0}, {0,AT_FOLD_UNITY} },
/* 3: L C R */
{ {AT_FOLD_UNITY,0}, {AT_FOLD_M3DB,AT_FOLD_M3DB}, {0,AT_FOLD_UNITY} },
/* 4: L R RL RR */
{ {AT_FOLD_UNITY,0}, {0,AT_FOLD_UNITY},
{AT_FOLD_M3DB,0}, {0,AT_FOLD_M3DB} },
/* 5: L C R RL RR */
{ {AT_FOLD_UNITY,0}, {AT_FOLD_M3DB,AT_FOLD_M3DB}, {0,AT_FOLD_UNITY},
{AT_FOLD_M3DB,0}, {0,AT_FOLD_M3DB} },
/* 6: L C R RL RR LFE */
{ {AT_FOLD_UNITY,0}, {AT_FOLD_M3DB,AT_FOLD_M3DB}, {0,AT_FOLD_UNITY},
{AT_FOLD_M3DB,0}, {0,AT_FOLD_M3DB}, {0,0} },
/* 7: L C R RL RR BC LFE */
{ {AT_FOLD_UNITY,0}, {AT_FOLD_M3DB,AT_FOLD_M3DB}, {0,AT_FOLD_UNITY},
{AT_FOLD_M3DB,0}, {0,AT_FOLD_M3DB},
{AT_FOLD_M6DB,AT_FOLD_M6DB}, {0,0} },
/* 8: L C R RL RR SL SR LFE */
{ {AT_FOLD_UNITY,0}, {AT_FOLD_M3DB,AT_FOLD_M3DB}, {0,AT_FOLD_UNITY},
{AT_FOLD_M3DB,0}, {0,AT_FOLD_M3DB},
{AT_FOLD_M3DB,0}, {0,AT_FOLD_M3DB}, {0,0} }
};
static const int32_t audio_transfer_fold_wav[9][8][2] = {
{ {0,0} },
{ {AT_FOLD_UNITY,AT_FOLD_UNITY} },
{ {AT_FOLD_UNITY,0}, {0,AT_FOLD_UNITY} },
/* 3: FL FR FC */
{ {AT_FOLD_UNITY,0}, {0,AT_FOLD_UNITY}, {AT_FOLD_M3DB,AT_FOLD_M3DB} },
/* 4: FL FR BL BR */
{ {AT_FOLD_UNITY,0}, {0,AT_FOLD_UNITY},
{AT_FOLD_M3DB,0}, {0,AT_FOLD_M3DB} },
/* 5: FL FR FC BL BR */
{ {AT_FOLD_UNITY,0}, {0,AT_FOLD_UNITY}, {AT_FOLD_M3DB,AT_FOLD_M3DB},
{AT_FOLD_M3DB,0}, {0,AT_FOLD_M3DB} },
/* 6: FL FR FC LFE BL BR */
{ {AT_FOLD_UNITY,0}, {0,AT_FOLD_UNITY}, {AT_FOLD_M3DB,AT_FOLD_M3DB},
{0,0}, {AT_FOLD_M3DB,0}, {0,AT_FOLD_M3DB} },
/* 7: FL FR FC LFE BC SL SR */
{ {AT_FOLD_UNITY,0}, {0,AT_FOLD_UNITY}, {AT_FOLD_M3DB,AT_FOLD_M3DB},
{0,0}, {AT_FOLD_M6DB,AT_FOLD_M6DB},
{AT_FOLD_M3DB,0}, {0,AT_FOLD_M3DB} },
/* 8: FL FR FC LFE BL BR SL SR */
{ {AT_FOLD_UNITY,0}, {0,AT_FOLD_UNITY}, {AT_FOLD_M3DB,AT_FOLD_M3DB},
{0,0}, {AT_FOLD_M3DB,0}, {0,AT_FOLD_M3DB},
{AT_FOLD_M3DB,0}, {0,AT_FOLD_M3DB} }
};
const int32_t (*audio_transfer_fold_q15(enum audio_type_enum type,
unsigned channels))[2]
{
if (channels < 1 || channels > 8)
return NULL;
if (type == AUDIO_TYPE_VORBIS || type == AUDIO_TYPE_OPUS)
return audio_transfer_fold_vorbis[channels];
return audio_transfer_fold_wav[channels];
}
bool audio_transfer_stereo_matrix(void *data, enum audio_type_enum type,
int32_t matrix[8][2])
{
const int32_t (*fold)[2];
unsigned ch = 0;
if (!data || !matrix)
return false;
#ifdef HAVE_RWMA
/* by the stream's speaker mask */
if (type == AUDIO_TYPE_WMA)
if (data && matrix && type == AUDIO_TYPE_WMA)
{
static const uint32_t defaults[9] = {0,4,3,7,51,55,63,1807,1599};
struct audio_transfer_wma *a = (struct audio_transfer_wma*)data;
@@ -5161,14 +4425,10 @@ bool audio_transfer_stereo_matrix(void *data, enum audio_type_enum type,
}
return lane == a->channels;
}
#else
(void)data; (void)type; (void)matrix;
#endif
/* by the channel count, in the order the arm hands them over */
if ( !audio_transfer_info(data, type, &ch, NULL, NULL)
|| !(fold = audio_transfer_fold_q15(type, ch)))
return false;
memset(matrix, 0, 8 * 2 * sizeof(int32_t));
memcpy(matrix, fold, ch * 2 * sizeof(int32_t));
return true;
return false;
}
bool audio_transfer_stereo_matrix_f32(void *data, enum audio_type_enum type,
@@ -5195,9 +4455,7 @@ bool audio_transfer_info(void *data, enum audio_type_enum type,
if (!a || !a->stream) return false;
if (channels) *channels = a->channels;
if (rate) *rate = a->rate;
/* what the container states: the decode runs on past it by
* the codec's priming */
if (total_frames) *total_frames = rwma_stream_frames(a->stream);
if (total_frames) *total_frames = 0;
return true;
}
#endif
@@ -5344,18 +4602,6 @@ bool audio_transfer_info(void *data, enum audio_type_enum type,
return true;
}
#endif
#if defined(HAVE_RATRAC3) || defined(HAVE_RATRAC3P)
case AUDIO_TYPE_ATRAC:
{
struct audio_transfer_atrac *a = (struct audio_transfer_atrac*)data;
if (!a || !a->raw)
return false;
if (channels) *channels = a->channels;
if (rate) *rate = a->rate;
if (total_frames) *total_frames = a->total_frames;
return true;
}
#endif
#ifdef HAVE_RAC3
case AUDIO_TYPE_AC3:
{
@@ -6850,11 +6096,6 @@ int audio_transfer_read_s16(void *data, enum audio_type_enum type,
break;
}
#endif
#if defined(HAVE_RATRAC3) || defined(HAVE_RATRAC3P)
case AUDIO_TYPE_ATRAC:
return audio_transfer_atrac_read((struct audio_transfer_atrac*)data,
NULL, out, frames, frames_out);
#endif
#ifdef HAVE_RAC3
case AUDIO_TYPE_AC3:
return audio_transfer_ac3_read((struct audio_transfer_ac3*)data,
@@ -7179,11 +6420,6 @@ int audio_transfer_read_f32(void *data, enum audio_type_enum type,
break;
}
#endif
#if defined(HAVE_RATRAC3) || defined(HAVE_RATRAC3P)
case AUDIO_TYPE_ATRAC:
return audio_transfer_atrac_read((struct audio_transfer_atrac*)data,
out, NULL, frames, frames_out);
#endif
#ifdef HAVE_RAC3
case AUDIO_TYPE_AC3:
return audio_transfer_ac3_read((struct audio_transfer_ac3*)data,
@@ -7399,13 +6635,6 @@ size_t audio_transfer_buffer_tell(void *data, enum audio_type_enum type)
return 0;
}
#endif
#if defined(HAVE_RATRAC3) || defined(HAVE_RATRAC3P)
case AUDIO_TYPE_ATRAC:
{
struct audio_transfer_atrac *a = (struct audio_transfer_atrac*)data;
return a ? a->pos : 0;
}
#endif
#ifdef HAVE_RAC3
case AUDIO_TYPE_AC3:
{
@@ -7762,15 +6991,6 @@ bool audio_transfer_seek(void *data, enum audio_type_enum type,
return true;
}
#endif
#if defined(HAVE_RATRAC3) || defined(HAVE_RATRAC3P)
case AUDIO_TYPE_ATRAC:
{
struct audio_transfer_atrac *a = (struct audio_transfer_atrac*)data;
if (!a || !a->raw)
return false;
return audio_transfer_atrac_seek_to(a, frame);
}
#endif
#ifdef HAVE_RAC3
case AUDIO_TYPE_AC3:
{
@@ -7937,24 +7157,6 @@ void audio_transfer_free(void *data, enum audio_type_enum type)
break;
}
#endif
#if defined(HAVE_RATRAC3) || defined(HAVE_RATRAC3P)
case AUDIO_TYPE_ATRAC:
{
struct audio_transfer_atrac *a = (struct audio_transfer_atrac*)data;
if (a)
{
#ifdef HAVE_RATRAC3P
ratrac3p_free(a->d3p);
#endif
#ifdef HAVE_RATRAC3
ratrac3_free(a->d3);
#endif
free(a->raw);
free(a->pend);
}
break;
}
#endif
#ifdef HAVE_RAC3
case AUDIO_TYPE_AC3:
{
@@ -1,248 +0,0 @@
/* Copyright (C) 2010-2026 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (rcontainer.c).
* ---------------------------------------------------------------------------------------
*
* Permission is hereby granted, free of charge,
* to any person obtaining a copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/* AVI and ASF headers: see formats/rcontainer.h. */
#include <string.h>
#include <formats/rcontainer.h>
static uint32_t rc_le16(const uint8_t *p) { return (uint32_t)p[0] | ((uint32_t)p[1] << 8); }
static uint32_t rc_le32(const uint8_t *p)
{
return (uint32_t)p[0] | ((uint32_t)p[1] << 8) | ((uint32_t)p[2] << 16) | ((uint32_t)p[3] << 24);
}
static uint64_t rc_le64(const uint8_t *p)
{
return (uint64_t)rc_le32(p) | ((uint64_t)rc_le32(p + 4) << 32);
}
/* a WAVEFORMATEX into an audio stream */
static void rc_wave(rcontainer_stream *s, const uint8_t *p, size_t n)
{
s->type = RCONTAINER_STREAM_AUDIO;
if (n < 16)
return;
s->format_tag = rc_le16(p);
s->channels = rc_le16(p + 2);
s->sample_rate = rc_le32(p + 4);
s->bitrate = rc_le32(p + 8) * 8;
/* WAVE_FORMAT_EXTENSIBLE: the sub-format's first two bytes */
if (s->format_tag == 0xFFFE && n >= 26 && rc_le16(p + 16) >= 22)
s->format_tag = rc_le16(p + 24);
}
/* a BITMAPINFOHEADER into a video stream */
static void rc_bitmap(rcontainer_stream *s, const uint8_t *p, size_t n)
{
int32_t h;
s->type = RCONTAINER_STREAM_VIDEO;
if (n < 20)
return;
s->width = rc_le32(p + 4);
h = (int32_t)rc_le32(p + 8);
s->height = (unsigned)(h < 0 ? -h : h);
s->fourcc = rc_le32(p + 16);
}
/* ---------------------------------------------------------------- */
/* AVI */
/* ---------------------------------------------------------------- */
/* the chunk of @id among those in [@at, @end): its body */
static bool rc_chunk(const uint8_t *p, size_t at, size_t end, const char *id,
const char *list, size_t *body, size_t *body_end)
{
while (at + 8 <= end)
{
size_t len = rc_le32(p + at + 4);
if (len > end - at - 8)
len = end - at - 8;
if (!memcmp(p + at, id, 4) && (!list || (len >= 4 && !memcmp(p + at + 8, list, 4))))
{
*body = at + 8 + (list ? 4 : 0);
*body_end = at + 8 + len;
return true;
}
at += 8 + len + (len & 1);
}
return false;
}
static bool rc_avi(const uint8_t *p, size_t n, rcontainer_info *info)
{
size_t hdrl, hdrl_end, b, b_end, at;
uint64_t frames = 0, period = 0, bytes[RCONTAINER_MAX_STREAMS];
double seconds = 0;
unsigned i;
if (!rc_chunk(p, 12, n, "LIST", "hdrl", &hdrl, &hdrl_end))
return false;
info->kind = RCONTAINER_AVI;
if (rc_chunk(p, hdrl, hdrl_end, "avih", NULL, &b, &b_end) && b_end - b >= 20)
{
period = rc_le32(p + b); /* microseconds a frame */
frames = rc_le32(p + b + 16);
}
/* each stream list in turn */
for (at = hdrl; at + 8 <= hdrl_end; )
{
size_t len = rc_le32(p + at + 4), sl, sl_end, h, h_end, f, f_end;
if (len > hdrl_end - at - 8)
len = hdrl_end - at - 8;
if (!memcmp(p + at, "LIST", 4) && len >= 4 && !memcmp(p + at + 8, "strl", 4)
&& info->num_streams < RCONTAINER_MAX_STREAMS)
{
rcontainer_stream *s = &info->streams[info->num_streams++];
sl = at + 12;
sl_end = at + 8 + len;
if (rc_chunk(p, sl, sl_end, "strh", NULL, &h, &h_end) && h_end - h >= 36)
{
uint32_t scale = rc_le32(p + h + 20), rate = rc_le32(p + h + 24);
uint32_t length = rc_le32(p + h + 32);
if (rc_chunk(p, sl, sl_end, "strf", NULL, &f, &f_end))
{
if (!memcmp(p + h, "vids", 4))
rc_bitmap(s, p + f, f_end - f);
else if (!memcmp(p + h, "auds", 4))
rc_wave(s, p + f, f_end - f);
}
/* the longest stream's length is the file's, as FFmpeg
* gives it */
if (scale && rate && (double)length * scale / rate > seconds)
seconds = (double)length * scale / rate;
}
}
at += 8 + len + (len & 1);
}
if (!seconds && frames && period)
seconds = (double)frames * period / 1e6;
info->duration_us = (int64_t)(seconds * 1e6 + 0.5);
/* each stream's bytes, from idx1: "NNxx" ids, NN the stream */
memset(bytes, 0, sizeof(bytes));
if (seconds > 0 && rc_chunk(p, 12, n, "idx1", NULL, &b, &b_end))
{
for (at = b; at + 16 <= b_end; at += 16)
{
unsigned d0 = p[at], d1 = p[at + 1], k;
if (d0 < '0' || d0 > '9' || d1 < '0' || d1 > '9')
continue;
k = (d0 - '0') * 10 + (d1 - '0');
if (k < info->num_streams)
bytes[k] += rc_le32(p + at + 12);
}
for (i = 0; i < info->num_streams; i++)
if (bytes[i] && info->streams[i].type == RCONTAINER_STREAM_VIDEO)
info->streams[i].bitrate = (uint32_t)(bytes[i] * 8 / seconds);
}
return info->num_streams > 0;
}
/* ---------------------------------------------------------------- */
/* ASF */
/* ---------------------------------------------------------------- */
static const uint8_t rc_asf_header[16] = { 0x30,0x26,0xB2,0x75,0x8E,0x66,0xCF,0x11,0xA6,0xD9,0x00,0xAA,0x00,0x62,0xCE,0x6C };
static const uint8_t rc_asf_file[16] = { 0xA1,0xDC,0xAB,0x8C,0x47,0xA9,0xCF,0x11,0x8E,0xE4,0x00,0xC0,0x0C,0x20,0x53,0x65 };
static const uint8_t rc_asf_stream[16] = { 0x91,0x07,0xDC,0xB7,0xB7,0xA9,0xCF,0x11,0x8E,0xE6,0x00,0xC0,0x0C,0x20,0x53,0x65 };
static const uint8_t rc_asf_audio[16] = { 0x40,0x9E,0x69,0xF8,0x4D,0x5B,0xCF,0x11,0xA8,0xFD,0x00,0x80,0x5F,0x5C,0x44,0x2B };
static const uint8_t rc_asf_video[16] = { 0xC0,0xEF,0x19,0xBC,0x4D,0x5B,0xCF,0x11,0xA8,0xFD,0x00,0x80,0x5F,0x5C,0x44,0x2B };
static const uint8_t rc_asf_bitrate[16] = { 0xCE,0x75,0xF8,0x7B,0x8D,0x46,0xD1,0x11,0x8D,0x82,0x00,0x60,0x97,0xC9,0xA2,0xB2 };
static bool rc_asf(const uint8_t *p, size_t n, rcontainer_info *info)
{
uint64_t size = rc_le64(p + 16);
size_t end = size < n ? (size_t)size : n, at = 30;
unsigned number[RCONTAINER_MAX_STREAMS], i;
uint32_t rates[128];
info->kind = RCONTAINER_ASF;
memset(rates, 0, sizeof(rates));
while (at + 24 <= end)
{
uint64_t osize = rc_le64(p + at + 16);
size_t body = at + 24, oend;
if (osize < 24 || osize > end - at)
break;
oend = at + (size_t)osize;
if (!memcmp(p + at, rc_asf_file, 16) && oend - body >= 68)
{
uint64_t play = rc_le64(p + body + 40), preroll = rc_le64(p + body + 56);
if (!(rc_le32(p + body + 64) & 1) && preroll < play / 10000)
info->duration_us = (int64_t)((play - preroll * 10000) / 10);
}
else if (!memcmp(p + at, rc_asf_stream, 16) && oend - body >= 54
&& info->num_streams < RCONTAINER_MAX_STREAMS)
{
rcontainer_stream *s = &info->streams[info->num_streams];
uint32_t tlen = rc_le32(p + body + 40);
size_t t = body + 54;
number[info->num_streams++] = rc_le16(p + body + 48) & 0x7f;
if (tlen > oend - t)
tlen = (uint32_t)(oend - t);
if (!memcmp(p + body, rc_asf_audio, 16))
rc_wave(s, p + t, tlen);
else if (!memcmp(p + body, rc_asf_video, 16))
{
/* width, height, a flag byte, the format data's size, then
* a BITMAPINFOHEADER */
s->type = RCONTAINER_STREAM_VIDEO;
if (tlen >= 11)
rc_bitmap(s, p + t + 11, tlen - 11);
if (tlen >= 8)
{
s->width = rc_le32(p + t);
s->height = rc_le32(p + t + 4);
}
}
}
else if (!memcmp(p + at, rc_asf_bitrate, 16) && oend - body >= 2)
{
unsigned count = rc_le16(p + body), k;
for (k = 0; k < count && body + 2 + k * 6 + 6 <= oend; k++)
{
const uint8_t *r = p + body + 2 + k * 6;
rates[rc_le16(r) & 0x7f] = rc_le32(r + 2);
}
}
at = oend;
}
for (i = 0; i < info->num_streams; i++)
if (rates[number[i]])
info->streams[i].bitrate = rates[number[i]];
return info->num_streams > 0;
}
bool rcontainer_probe(const uint8_t *data, size_t len, rcontainer_info *info)
{
if (!info)
return false;
memset(info, 0, sizeof(*info));
if (!data)
return false;
if (len >= 12 && !memcmp(data, "RIFF", 4) && !memcmp(data + 8, "AVI ", 4))
return rc_avi(data, len, info);
if (len >= 30 && !memcmp(data, rc_asf_header, 16))
return rc_asf(data, len, info);
return false;
}
-4
View File
@@ -1259,10 +1259,6 @@ static int data_transfer_read_at(data_transfer_t *dt, size_t off,
int64_t save, r;
if (dt->read_at)
return dt->read_at(dt->read_ud,off,dst,n) == (int64_t)n;
/* At the offset, the cursor and read-ahead untouched; seek and read
* where the file has no positional reads */
if ((r = filestream_read_at(dt->f, dst, (int64_t)n, (int64_t)off)) >= 0)
return r == (int64_t)n;
save = filestream_tell(dt->f);
if (save < 0
|| (save != (int64_t)off
+20 -112
View File
@@ -66,7 +66,6 @@
#include <limits.h>
#include <retro_inline.h>
#include <retro_endianness.h>
#include <formats/image.h>
#include <formats/rdds.h>
@@ -91,20 +90,7 @@
( (unsigned long long)RDDS_RL32((const unsigned char*)(p)) \
| ((unsigned long long)RDDS_RL32((const unsigned char*)(p) + 4) << 32))
/* Inlined into each of its callers whatever the compiler would choose, so
* that a decoder taking a constant order (RGBA or BGRA) is built for it
* alone, with no test of the order per block. */
#if defined(_MSC_VER)
#define RDDS_FORCE_INLINE static __forceinline
#elif defined(__GNUC__)
#define RDDS_FORCE_INLINE static INLINE __attribute__((always_inline))
#else
#define RDDS_FORCE_INLINE static INLINE
#endif
/* bgra: B,G,R,A in memory instead of R,G,B,A (red and blue swapped in
* the reference colours) */
RDDS_FORCE_INLINE void rdds_bcdec__color_block_order(const void* compressedBlock, void* decompressedBlock, int destinationPitch, int onlyOpaqueMode, int bgra) {
static void rdds_bcdec__color_block(const void* compressedBlock, void* decompressedBlock, int destinationPitch, int onlyOpaqueMode) {
unsigned short c0, c1;
unsigned int refColors[4]; /* 0xAABBGGRR */
unsigned char* dstColors;
@@ -160,12 +146,6 @@ RDDS_FORCE_INLINE void rdds_bcdec__color_block_order(const void* compressedBlock
colorIndices = RDDS_RL32((const unsigned char*)compressedBlock + 4);
if (bgra) {
for (i = 0; i < 4; ++i)
refColors[i] = (refColors[i] & 0xFF00FF00u) | ((refColors[i] >> 16) & 0xFFu)
| ((refColors[i] & 0xFFu) << 16);
}
/* Fill out the decompressed color block */
dstColors = (unsigned char*)decompressedBlock;
for (i = 0; i < 4; ++i) {
@@ -182,14 +162,6 @@ RDDS_FORCE_INLINE void rdds_bcdec__color_block_order(const void* compressedBlock
}
}
static void rdds_bcdec__color_block(const void* compressedBlock, void* decompressedBlock, int destinationPitch, int onlyOpaqueMode) {
rdds_bcdec__color_block_order(compressedBlock, decompressedBlock, destinationPitch, onlyOpaqueMode, 0);
}
static void rdds_bcdec__color_block_bgra(const void* compressedBlock, void* decompressedBlock, int destinationPitch, int onlyOpaqueMode) {
rdds_bcdec__color_block_order(compressedBlock, decompressedBlock, destinationPitch, onlyOpaqueMode, 1);
}
static void rdds_bcdec__sharp_alpha_block(const void* compressedBlock, void* decompressedBlock, int destinationPitch) {
const unsigned char* alpha;
unsigned char* decompressed;
@@ -418,21 +390,6 @@ static void rdds_bcdec_bc3(const void* compressedBlock, void* decompressedBlock,
rdds_bcdec__smooth_alpha_block(compressedBlock, ((char*)decompressedBlock) + 3, destinationPitch, 4);
}
/* The same, B,G,R,A in memory: alpha stays the fourth byte */
static void rdds_bcdec_bc1_bgra(const void* compressedBlock, void* decompressedBlock, int destinationPitch) {
rdds_bcdec__color_block_bgra(compressedBlock, decompressedBlock, destinationPitch, 0);
}
static void rdds_bcdec_bc2_bgra(const void* compressedBlock, void* decompressedBlock, int destinationPitch) {
rdds_bcdec__color_block_bgra(((char*)compressedBlock) + 8, decompressedBlock, destinationPitch, 1);
rdds_bcdec__sharp_alpha_block(compressedBlock, ((char*)decompressedBlock) + 3, destinationPitch);
}
static void rdds_bcdec_bc3_bgra(const void* compressedBlock, void* decompressedBlock, int destinationPitch) {
rdds_bcdec__color_block_bgra(((char*)compressedBlock) + 8, decompressedBlock, destinationPitch, 1);
rdds_bcdec__smooth_alpha_block(compressedBlock, ((char*)decompressedBlock) + 3, destinationPitch, 4);
}
#ifndef BCDEC_BC4BC5_PRECISE
static void rdds_bcdec_bc4(const void* compressedBlock, void* decompressedBlock, int destinationPitch) {
rdds_bcdec__smooth_alpha_block(compressedBlock, decompressedBlock, destinationPitch, 1);
@@ -1934,7 +1891,7 @@ static const unsigned char rdds_d6[190] = {
* stores the compiler already coalesces, so it needs no fused variant
* and no punch-through handling here.) */
static INLINE void rdds_bc_refcolors(const unsigned char *cp,
unsigned int ref[4], int bgra)
unsigned int ref[4])
{
unsigned c0 = RDDS_RL16(cp), c1 = RDDS_RL16(cp + 2);
unsigned r0 = (c0 >> 11) & 0x1F, g0 = (c0 >> 5) & 0x3F, b0 = c0 & 0x1F;
@@ -1948,19 +1905,11 @@ static INLINE void rdds_bc_refcolors(const unsigned char *cp,
| ((unsigned)rdds_d6[2 * g0 + g1] << 8) | rdds_d5[2 * r0 + r1];
ref[3] = 0xFF000000u | ((unsigned)rdds_d5[b0 + 2 * b1] << 16)
| ((unsigned)rdds_d6[g0 + 2 * g1] << 8) | rdds_d5[r0 + 2 * r1];
if (bgra) /* A<<24|R<<16|G<<8|B, for a BGRA surface */
{
int k;
for (k = 0; k < 4; k++)
ref[k] = (ref[k] & 0xFF00FF00u) | ((ref[k] >> 16) & 0xFFu)
| ((ref[k] & 0xFFu) << 16);
}
}
/* BC2: opaque colour + explicit 4-bit alpha, fused into one store.
* bgra: the uint32 is A<<24|R<<16|G<<8|B instead of A<<24|B<<16|G<<8|R. */
RDDS_FORCE_INLINE void rdds_bcdec_bc2_fused(const void *compressedBlock,
void *decompressedBlock, int destinationPitch, int bgra)
/* BC2: opaque colour + explicit 4-bit alpha, fused into one store. */
static void rdds_bcdec_bc2_direct(const void *compressedBlock,
void *decompressedBlock, int destinationPitch)
{
const unsigned char *p = (const unsigned char*)compressedBlock;
unsigned char *dst = (unsigned char*)decompressedBlock;
@@ -1968,7 +1917,7 @@ RDDS_FORCE_INLINE void rdds_bcdec_bc2_fused(const void *compressedBlock,
unsigned int ci = RDDS_RL32(p + 12);
int i, j;
rdds_bc_refcolors(p + 8, ref, bgra);
rdds_bc_refcolors(p + 8, ref);
for (i = 0; i < 4; ++i)
{
unsigned int arow = RDDS_RL16(p + 2 * i); /* four 4-bit alphas */
@@ -1985,11 +1934,9 @@ RDDS_FORCE_INLINE void rdds_bcdec_bc2_fused(const void *compressedBlock,
}
}
/* BC3: opaque colour + smooth (interpolated) 8-value alpha, one store.
* The alpha ramp rounds as rdds_bcdec__smooth_alpha_block does, so this
* path and the scratch one agree for every texel. */
RDDS_FORCE_INLINE void rdds_bcdec_bc3_fused(const void *compressedBlock,
void *decompressedBlock, int destinationPitch, int bgra)
/* BC3: opaque colour + smooth (interpolated) 8-value alpha, one store. */
static void rdds_bcdec_bc3_direct(const void *compressedBlock,
void *decompressedBlock, int destinationPitch)
{
const unsigned char *p = (const unsigned char*)compressedBlock;
unsigned char *dst = (unsigned char*)decompressedBlock;
@@ -2004,24 +1951,24 @@ RDDS_FORCE_INLINE void rdds_bcdec_bc3_fused(const void *compressedBlock,
al[1] = (unsigned char)((blk >> 8) & 0xFF);
if (al[0] > al[1])
{
al[2] = (unsigned char)((6 * al[0] + al[1] + 3) / 7);
al[3] = (unsigned char)((5 * al[0] + 2 * al[1] + 3) / 7);
al[4] = (unsigned char)((4 * al[0] + 3 * al[1] + 3) / 7);
al[5] = (unsigned char)((3 * al[0] + 4 * al[1] + 3) / 7);
al[6] = (unsigned char)((2 * al[0] + 5 * al[1] + 3) / 7);
al[7] = (unsigned char)(( al[0] + 6 * al[1] + 3) / 7);
al[2] = (unsigned char)((6 * al[0] + al[1]) / 7);
al[3] = (unsigned char)((5 * al[0] + 2 * al[1]) / 7);
al[4] = (unsigned char)((4 * al[0] + 3 * al[1]) / 7);
al[5] = (unsigned char)((3 * al[0] + 4 * al[1]) / 7);
al[6] = (unsigned char)((2 * al[0] + 5 * al[1]) / 7);
al[7] = (unsigned char)(( al[0] + 6 * al[1]) / 7);
}
else
{
al[2] = (unsigned char)((4 * al[0] + al[1] + 2) / 5);
al[3] = (unsigned char)((3 * al[0] + 2 * al[1] + 2) / 5);
al[4] = (unsigned char)((2 * al[0] + 3 * al[1] + 2) / 5);
al[5] = (unsigned char)(( al[0] + 4 * al[1] + 2) / 5);
al[2] = (unsigned char)((4 * al[0] + al[1]) / 5);
al[3] = (unsigned char)((3 * al[0] + 2 * al[1]) / 5);
al[4] = (unsigned char)((2 * al[0] + 3 * al[1]) / 5);
al[5] = (unsigned char)(( al[0] + 4 * al[1]) / 5);
al[6] = 0x00;
al[7] = 0xFF;
}
rdds_bc_refcolors(p + 8, ref, bgra);
rdds_bc_refcolors(p + 8, ref);
ci = RDDS_RL32(p + 12);
idx = blk >> 16; /* 16 * 3-bit indices */
for (i = 0; i < 4; ++i)
@@ -2038,15 +1985,6 @@ RDDS_FORCE_INLINE void rdds_bcdec_bc3_fused(const void *compressedBlock,
}
}
static void rdds_bcdec_bc2_direct(const void *b, void *o, int pitch)
{ rdds_bcdec_bc2_fused(b, o, pitch, 0); }
static void rdds_bcdec_bc3_direct(const void *b, void *o, int pitch)
{ rdds_bcdec_bc3_fused(b, o, pitch, 0); }
static void rdds_bcdec_bc2_direct_bgra(const void *b, void *o, int pitch)
{ rdds_bcdec_bc2_fused(b, o, pitch, 1); }
static void rdds_bcdec_bc3_direct_bgra(const void *b, void *o, int pitch)
{ rdds_bcdec_bc3_fused(b, o, pitch, 1); }
/* Emit an edge (partially out-of-range) block from a decoded RGBA8
* scratch into the surface with per-texel bounds tests. Shared by every
* path so the hot interior loops stay branch-free. */
@@ -2122,17 +2060,6 @@ RDDS_GEN_ROWS_DIRECT(rdds_rows_bc1_rgba, rdds_bcdec_bc1, 8u)
RDDS_GEN_ROWS_DIRECT(rdds_rows_bc2_rgba, rdds_bcdec_bc2_direct, 16u)
RDDS_GEN_ROWS_DIRECT(rdds_rows_bc3_rgba, rdds_bcdec_bc3_direct, 16u)
#ifndef MSB_FIRST
/* The same for a BGRA video driver, little-endian only: there the
* A<<24|R<<16|G<<8|B pixel is the bytes B,G,R,A, which the BGRA block
* decoders write, so the edge scratch passes through rdds_emit_edge's
* byte order unchanged (as with RGBA). Big-endian keeps the scratch
* path below. */
RDDS_GEN_ROWS_DIRECT(rdds_rows_bc1_bgra, rdds_bcdec_bc1_bgra, 8u)
RDDS_GEN_ROWS_DIRECT(rdds_rows_bc2_bgra, rdds_bcdec_bc2_direct_bgra, 16u)
RDDS_GEN_ROWS_DIRECT(rdds_rows_bc3_bgra, rdds_bcdec_bc3_direct_bgra, 16u)
#endif
/* Decode block rows [by0, by1) of a BCn surface into 'out'. The caller
* has already validated that the payload holds every block. */
static void rdds_rows_compressed(const rdds_info_t *info,
@@ -2166,22 +2093,6 @@ static void rdds_rows_compressed(const rdds_info_t *info,
break; /* BC4/BC5/BC7 fall through to the scratch loop */
}
}
#ifndef MSB_FIRST
else if (!premul)
{
switch (info->fmt)
{
case RDDS_FMT_BC1:
rdds_rows_bc1_bgra(info, data, out, by0, by1); return;
case RDDS_FMT_BC2:
rdds_rows_bc2_bgra(info, data, out, by0, by1); return;
case RDDS_FMT_BC3:
rdds_rows_bc3_bgra(info, data, out, by0, by1); return;
default:
break;
}
}
#endif
/* Generic scratch path: BGRA output order, premultiplied alpha,
* BC4/BC5 channel expansion, and BC7 (whose decode dominates, so the
@@ -2811,6 +2722,3 @@ void rdds_decode_block_bc1(const void *block, void *out, int pitch) { rdds_bcdec
void rdds_decode_block_bc2(const void *block, void *out, int pitch) { rdds_bcdec_bc2(block, out, pitch); }
void rdds_decode_block_bc3(const void *block, void *out, int pitch) { rdds_bcdec_bc3(block, out, pitch); }
void rdds_decode_block_bc7(const void *block, void *out, int pitch) { rdds_bcdec_bc7(block, out, pitch); }
void rdds_decode_block_bc1_bgra(const void *block, void *out, int pitch) { rdds_bcdec_bc1_bgra(block, out, pitch); }
void rdds_decode_block_bc2_bgra(const void *block, void *out, int pitch) { rdds_bcdec_bc2_bgra(block, out, pitch); }
void rdds_decode_block_bc3_bgra(const void *block, void *out, int pitch) { rdds_bcdec_bc3_bgra(block, out, pitch); }
+1 -7
View File
@@ -131,13 +131,7 @@ bool rdvd_vfs_service(rdvd_vfs_t *vfs)
memset(&result, 0, sizeof(result));
result.ticket = request.ticket; result.bytes = -1;
bytes = request.bytes < 65536 ? request.bytes : 65536;
/* At the offset in one call; seek and read where there is none */
if ((result.bytes = filestream_read_at(request.file, request.destination,
(int64_t)bytes, (int64_t)request.offset)) >= 0)
{
if (result.bytes > (int64_t)bytes) result.bytes = -1;
}
else if (filestream_seek(request.file, (int64_t)request.offset,
if (filestream_seek(request.file, (int64_t)request.offset,
RETRO_VFS_SEEK_POSITION_START) == 0
&& filestream_tell(request.file) == (int64_t)request.offset)
{
+17 -680
View File
@@ -20,37 +20,27 @@
* THE SOFTWARE.
*/
#include <formats/rflv_mux.h>
#include <formats/rav1_sequence.h>
#include <stdlib.h>
#include <string.h>
enum flv_output
{
FLV_HEADER, FLV_COLOR, FLV_VIDEO_CONFIG, FLV_AUDIO_CONFIG, FLV_MEDIA, FLV_IDLE
FLV_HEADER, FLV_VIDEO_CONFIG, FLV_AUDIO_CONFIG, FLV_MEDIA, FLV_IDLE
};
enum flv_codec { FLV_AVC, FLV_HEVC, FLV_AV1 };
struct rflv_mux
{
uint64_t last[2], input_dts;
rflv_span_t spans[3];
uint8_t *config;
uint8_t *converted;
uint8_t *metadata;
rav1_sequence_t *av1_sequence;
rav1_config_t av1_config;
const uint8_t *input;
size_t avcc_size, asc_size, limit, size, offset, span_count;
size_t converted_size;
size_t metadata_size;
uint32_t timestamp;
int32_t composition;
unsigned timescale[2], track;
enum flv_output output;
uint8_t prefix[19], suffix[4];
uint8_t prefix[16], suffix[4];
bool pending, scanning, failed, finished, seen[2], keyframe, vcl, idr;
bool annexb, hevc, av1;
};
static void flv_uint(uint8_t *out, uint32_t value, unsigned count)
@@ -100,42 +90,6 @@ static bool flv_avcc(const uint8_t *data, size_t size)
return flv_sets(data, size, &pos, count, 13) && pos == size;
}
static bool flv_hvcc(const uint8_t *data, size_t size)
{
size_t at = 23;
unsigned arrays, count, type, length, present = 0;
if (!data || size < 23 || size > 65536 || data[0] != 1
|| (data[13] & 0xf0) != 0xf0 || (data[15] & 0xfc) != 0xfc
|| (data[16] & 0xfc) != 0xfc || (data[17] & 0xf8) != 0xf8
|| (data[18] & 0xf8) != 0xf8
|| (data[21] & 3) != 3 || !data[22])
return false;
for (arrays = data[22]; arrays; arrays--)
{
if (size - at < 3 || (data[at] & 0x40))
return false;
type = data[at++] & 63;
count = ((unsigned)data[at] << 8) | data[at + 1];
at += 2;
if (!count)
return false;
while (count--)
{
if (size - at < 2)
return false;
length = ((unsigned)data[at] << 8) | data[at + 1];
at += 2;
if (length < 2 || length > size - at || (data[at] & 0x80)
|| ((data[at] >> 1) & 63) != type || !(data[at + 1] & 7))
return false;
at += length;
}
if (type >= 32 && type <= 34)
present |= 1u << (type - 32);
}
return at == size && present == 7;
}
static unsigned flv_bits(const uint8_t *data, size_t size, unsigned *pos, unsigned count)
{
unsigned i, value = 0;
@@ -169,7 +123,7 @@ static bool flv_asc(const uint8_t *data, size_t size)
static void flv_tag(rflv_mux_t *m, unsigned track, const void *data,
size_t size, uint32_t timestamp, int32_t composition, bool keyframe, bool config)
{
unsigned bytes = track == 1 ? (m->hevc && !config && composition ? 8 : 5) : 2;
unsigned bytes = track == 1 ? 5 : 2;
memset(m->prefix, 0, sizeof(m->prefix));
m->prefix[0] = track == 1 ? 9 : 8;
flv_uint(m->prefix + 1, (uint32_t)size + bytes, 3);
@@ -177,15 +131,7 @@ static void flv_tag(rflv_mux_t *m, unsigned track, const void *data,
m->prefix[7] = (uint8_t)(timestamp >> 24);
m->prefix[11] = track == 1 ? (keyframe ? 0x17 : 0x27) : 0xaf;
m->prefix[12] = config ? 0 : 1;
if (track == 1 && (m->hevc || m->av1))
{
m->prefix[11] = (uint8_t)(0x80 | (keyframe ? 0x10 : 0x20)
| (config ? 0 : m->av1 || composition ? 1 : 3));
memcpy(m->prefix + 12, m->av1 ? "av01" : "hvc1", 4);
if (bytes == 8)
flv_uint(m->prefix + 16, (uint32_t)composition, 3);
}
else if (track == 1)
if (track == 1)
flv_uint(m->prefix + 13, (uint32_t)composition, 3);
flv_uint(m->suffix, (uint32_t)size + bytes + 11, 4);
m->spans[0].data = m->prefix;
@@ -198,16 +144,11 @@ static void flv_tag(rflv_mux_t *m, unsigned track, const void *data,
m->pending = true;
}
static rflv_mux_t *flv_new(const rflv_config_t *c, enum flv_codec codec)
rflv_mux_t *rflv_mux_new(const rflv_config_t *c)
{
rflv_mux_t *m;
bool hevc = codec == FLV_HEVC, av1 = codec == FLV_AV1;
if (!c || (!c->avcc && !c->asc) || ((hevc || av1) && !c->avcc)
|| !c->max_packet_size || c->max_packet_size > (hevc ? 0xfffff7u : 0xfffffau)
|| (c->avcc ? !c->video_timescale
|| !(av1 ? c->avcc_size >= 4 && c->avcc_size <= 65536
: hevc ? flv_hvcc((const uint8_t*)c->avcc, c->avcc_size)
: flv_avcc((const uint8_t*)c->avcc, c->avcc_size))
if (!c || (!c->avcc && !c->asc) || !c->max_packet_size || c->max_packet_size > 0xfffffa
|| (c->avcc ? !c->video_timescale || !flv_avcc((const uint8_t*)c->avcc, c->avcc_size)
: c->avcc_size || c->video_timescale)
|| (c->asc ? !c->audio_timescale || !flv_asc((const uint8_t*)c->asc, c->asc_size)
: c->asc_size || c->audio_timescale))
@@ -230,18 +171,6 @@ static rflv_mux_t *flv_new(const rflv_config_t *c, enum flv_codec codec)
m->timescale[0] = c->video_timescale;
m->timescale[1] = c->audio_timescale;
m->limit = c->max_packet_size;
m->hevc = hevc;
m->av1 = av1;
if (av1)
{
m->av1_sequence = (rav1_sequence_t*)malloc(sizeof(*m->av1_sequence));
if (!m->av1_sequence || !rav1_config_parse(&m->av1_config, m->config, m->avcc_size)
|| !rav1_config_sequence(m->av1_sequence, &m->av1_config))
{
rflv_mux_free(m);
return NULL;
}
}
memcpy(m->prefix, "FLV\1\0\0\0\0\11\0\0\0\0", 13);
m->prefix[4] = (c->avcc ? 1 : 0) | (c->asc ? 4 : 0);
m->spans[0].data = m->prefix;
@@ -251,511 +180,6 @@ static rflv_mux_t *flv_new(const rflv_config_t *c, enum flv_codec codec)
return m;
}
rflv_mux_t *rflv_mux_new(const rflv_config_t *c)
{
return flv_new(c, FLV_AVC);
}
rflv_mux_t *rflv_mux_new_hevc(const rflv_config_t *c)
{
return flv_new(c, FLV_HEVC);
}
rflv_mux_t *rflv_mux_new_av1(const rflv_config_t *c)
{
return flv_new(c, FLV_AV1);
}
rflv_mux_t *rflv_mux_new_av1_obu(const rflv_config_t *c)
{
rav1_obu_t obu, sequence;
rav1_sequence_t *info;
rflv_config_t config;
rflv_mux_t *m = NULL;
uint8_t *data;
size_t at = 0, used;
int result;
if (!c || !c->avcc || !c->avcc_size || c->avcc_size > 65532)
return NULL;
memset(&sequence, 0, sizeof(sequence));
while ((result = rav1_obu_next(&obu, (const uint8_t*)c->avcc, c->avcc_size, &at, false)) > 0)
{
if (obu.type == 1)
{
if (sequence.data)
return NULL;
sequence = obu;
}
else if (obu.type != 2 && obu.type != 5 && obu.type != 15)
return NULL;
}
if (result < 0 || !sequence.data)
return NULL;
info = (rav1_sequence_t*)malloc(sizeof(*info));
if (!info)
return NULL;
if (!rav1_sequence_parse(info, sequence.payload, sequence.payload_size))
{
free(info);
return NULL;
}
data = (uint8_t*)malloc(c->avcc_size + 4);
if (data)
{
data[0] = 0x81;
data[1] = (uint8_t)((info->profile << 5) | info->operating_points[0].level);
data[2] = (uint8_t)((info->operating_points[0].tier << 7)
| ((info->bit_depth > 8) << 6) | ((info->bit_depth == 12) << 5)
| (info->monochrome << 4) | (info->subsampling_x << 3)
| (info->subsampling_y << 2) | info->chroma_sample_position);
data[3] = 0;
memcpy(data + 4, sequence.data, sequence.size);
used = sequence.size + 4;
at = 0;
while (rav1_obu_next(&obu, (const uint8_t*)c->avcc, c->avcc_size, &at, false) > 0)
if (obu.type == 5)
{
memcpy(data + used, obu.data, obu.size);
used += obu.size;
}
config = *c;
config.avcc = data;
config.avcc_size = used;
m = rflv_mux_new_av1(&config);
free(data);
}
free(info);
return m;
}
struct flv_metadata_writer
{
uint8_t *data;
size_t used;
bool failed;
};
static void flv_metadata_bytes(struct flv_metadata_writer *w,
const void *data, size_t size)
{
if (w->failed || size > 512 - w->used)
{
w->failed = true;
return;
}
memcpy(w->data + w->used, data, size);
w->used += size;
}
static void flv_metadata_name(struct flv_metadata_writer *w,
const char *name, bool property)
{
uint8_t header[3];
size_t size = strlen(name);
header[0] = 2;
header[1] = (uint8_t)(size >> 8);
header[2] = (uint8_t)size;
flv_metadata_bytes(w, header + (property ? 1 : 0), property ? 2 : 3);
flv_metadata_bytes(w, name, size);
}
static void flv_metadata_object(struct flv_metadata_writer *w, const char *name)
{
static const uint8_t marker = 3;
flv_metadata_name(w, name, true);
flv_metadata_bytes(w, &marker, 1);
}
static void flv_metadata_end(struct flv_metadata_writer *w)
{
static const uint8_t end[] = {0, 0, 9};
flv_metadata_bytes(w, end, sizeof(end));
}
/* Encode the nonnegative rational as binary64 without host float assumptions. */
static void flv_metadata_number(struct flv_metadata_writer *w, const char *name,
uint32_t numerator, unsigned denominator)
{
uint64_t n = numerator, d = denominator, fraction = 0, bits = 0, remainder;
int exponent = 0;
unsigned i;
if (n)
{
while (n < d)
{
n <<= 1;
exponent--;
}
while (n >= d * 2)
{
d <<= 1;
exponent++;
}
remainder = n - d;
for (i = 0; i < 52; i++)
{
remainder <<= 1;
fraction <<= 1;
if (remainder >= d)
{
remainder -= d;
fraction++;
}
}
if (remainder * 2 > d || (remainder * 2 == d && (fraction & 1)))
fraction++;
if (fraction == ((uint64_t)1 << 52))
{
fraction = 0;
exponent++;
}
bits = ((uint64_t)(exponent + 1023) << 52) | fraction;
}
flv_metadata_name(w, name, true);
if (w->failed || 512 - w->used < 9)
{
w->failed = true;
return;
}
w->data[w->used++] = 0;
for (i = 0; i < 8; i++)
w->data[w->used++] = (uint8_t)(bits >> (56 - i * 8));
}
bool rflv_mux_set_color(rflv_mux_t *m, const video_color_metadata_t *c,
unsigned depth)
{
static const char *const xy[] =
{ "redX", "redY", "greenX", "greenY", "blueX", "blueY", "whitePointX", "whitePointY" };
struct flv_metadata_writer w;
static const uint8_t object = 3;
unsigned i;
if (!m || !c || (!m->hevc && !m->av1) || m->failed || m->metadata
|| m->output != FLV_HEADER || !m->pending
|| (depth != 8 && depth != 10 && depth != 12)
|| (m->hevc && (depth != 8u + (m->config[17] & 7)
|| ((m->config[16] & 3) && depth != 8u + (m->config[18] & 7))))
|| (m->av1 && (depth != m->av1_sequence->bit_depth
|| (c->primaries && c->primaries != m->av1_sequence->color_primaries)
|| (c->transfer && c->transfer != m->av1_sequence->transfer_characteristics)
|| (c->matrix && c->matrix != m->av1_sequence->matrix_coefficients)
|| (c->range && c->range != m->av1_sequence->color_range + 1)))
|| c->primaries > 255 || c->transfer > 255 || c->matrix > 255
|| c->range > 2 || c->max_cll > 10000 || c->max_fall > 10000
|| (c->max_cll && c->max_fall > c->max_cll))
return false;
if (c->mastering.present)
{
if (c->mastering.present != VIDEO_MASTERING_DISPLAY_COMPLETE
|| c->mastering.luminance_max < 50000 || c->mastering.luminance_max > 100000000
|| !c->mastering.luminance_min || c->mastering.luminance_min > 50000)
return false;
for (i = 0; i < 8; i++)
if (c->mastering.chromaticity[i] < 5
|| c->mastering.chromaticity[i] > (i & 1 ? 42000 : 37000))
return false;
}
w.data = (uint8_t*)malloc(512);
if (!w.data)
return false;
w.used = 0;
w.failed = false;
flv_metadata_name(&w, "colorInfo", false);
flv_metadata_bytes(&w, &object, 1);
flv_metadata_object(&w, "colorConfig");
flv_metadata_number(&w, "bitDepth", depth, 1);
if (c->primaries)
flv_metadata_number(&w, "colorPrimaries", c->primaries, 1);
if (c->transfer)
flv_metadata_number(&w, "transferCharacteristics", c->transfer, 1);
if (c->matrix)
flv_metadata_number(&w, "matrixCoefficients", c->matrix, 1);
flv_metadata_end(&w);
if (c->max_cll || c->max_fall)
{
flv_metadata_object(&w, "hdrCll");
if (c->max_cll)
flv_metadata_number(&w, "maxCLL", c->max_cll, 1);
if (c->max_fall)
flv_metadata_number(&w, "maxFall", c->max_fall, 1);
flv_metadata_end(&w);
}
if (c->mastering.present)
{
flv_metadata_object(&w, "hdrMdcv");
for (i = 0; i < 8; i++)
flv_metadata_number(&w, xy[i], (c->mastering.chromaticity[i] + 2u) / 5, 10000);
flv_metadata_number(&w, "maxLuminance", c->mastering.luminance_max, 10000);
flv_metadata_number(&w, "minLuminance", c->mastering.luminance_min, 10000);
flv_metadata_end(&w);
}
flv_metadata_end(&w);
if (w.failed)
{
free(w.data);
return false;
}
m->metadata = w.data;
m->metadata_size = w.used;
return true;
}
static bool flv_annexb(const uint8_t *data, size_t size, size_t *offset,
const uint8_t **nal, size_t *length)
{
size_t start = *offset, at, zeros = 0, end;
while (start < size && !data[start])
start++;
if (start - *offset < 2 || start == size || data[start] != 1)
return false;
start++;
end = size;
for (at = start; at < size; at++)
{
if (!data[at])
zeros++;
else
{
if (data[at] == 1 && zeros >= 2)
{
end = at - zeros;
break;
}
zeros = 0;
}
}
*offset = at < size ? end : size;
if (at == size)
end -= zeros;
if (end <= start)
return false;
*nal = data + start;
*length = end - start;
return true;
}
struct flv_rbsp
{
const uint8_t *data;
size_t size, at;
unsigned byte, left, zeros;
bool failed;
};
static unsigned flv_rbsp_bits(struct flv_rbsp *b, unsigned count)
{
unsigned value = 0, next;
while (count--)
{
if (!b->left)
{
if (b->at == b->size)
goto failed;
next = b->data[b->at++];
if (b->zeros == 2 && next == 3)
{
if (b->at == b->size || b->data[b->at] > 3)
goto failed;
b->zeros = 0;
next = b->data[b->at++];
}
b->zeros = next ? 0 : b->zeros < 2 ? b->zeros + 1 : 2;
b->byte = next;
b->left = 8;
}
value = (value << 1) | ((b->byte >> --b->left) & 1);
}
return value;
failed:
b->failed = true;
return 0;
}
static unsigned flv_rbsp_ue(struct flv_rbsp *b)
{
unsigned zeros = 0;
while (!b->failed && !flv_rbsp_bits(b, 1))
if (++zeros == 32)
b->failed = true;
if (b->failed)
return ~0u;
return ((1u << zeros) - 1) + flv_rbsp_bits(b, zeros);
}
static bool flv_hevc_info(const uint8_t *sps, size_t size, uint8_t *header)
{
struct flv_rbsp b;
unsigned layers, nested, flags = 0, i, j, chroma, luma, chroma_depth;
memset(&b, 0, sizeof(b));
b.data = sps + 2;
b.size = size - 2;
flv_rbsp_bits(&b, 4);
layers = flv_rbsp_bits(&b, 3);
nested = flv_rbsp_bits(&b, 1);
if (layers > 6)
return false;
for (i = 1; i <= 12; i++)
header[i] = (uint8_t)flv_rbsp_bits(&b, 8);
for (i = 0; i < layers; i++)
flags |= flv_rbsp_bits(&b, 2) << (i * 2);
if (layers)
for (i = layers; i < 8; i++)
if (flv_rbsp_bits(&b, 2))
return false;
for (i = 0; i < layers; i++)
{
if (flags & (2u << (i * 2)))
for (j = 0; j < 11; j++)
flv_rbsp_bits(&b, 8);
if (flags & (1u << (i * 2)))
flv_rbsp_bits(&b, 8);
}
if (flv_rbsp_ue(&b) > 15)
return false;
chroma = flv_rbsp_ue(&b);
if (chroma > 3)
return false;
if (chroma == 3)
flv_rbsp_bits(&b, 1);
if (!flv_rbsp_ue(&b) || !flv_rbsp_ue(&b))
return false;
if (flv_rbsp_bits(&b, 1))
for (i = 0; i < 4; i++)
flv_rbsp_ue(&b);
luma = flv_rbsp_ue(&b);
chroma_depth = flv_rbsp_ue(&b);
if (b.failed || luma > 6 || chroma_depth > 6)
return false;
header[0] = 1;
header[13] = 0xf0;
header[15] = 0xfc;
header[16] = (uint8_t)(0xfc | chroma);
header[17] = (uint8_t)(0xf8 | luma);
header[18] = (uint8_t)(0xf8 | chroma_depth);
header[21] = (uint8_t)(((layers + 1) << 3) | (nested << 2) | 3);
header[22] = 3;
return true;
}
rflv_mux_t *rflv_mux_new_hevc_annexb(const rflv_config_t *c)
{
const uint8_t *sets[3] = {NULL, NULL, NULL}, *nal;
size_t lengths[3] = {0, 0, 0}, at = 0, size, total = 38;
unsigned type, i;
uint8_t *hvcc;
rflv_config_t config;
rflv_mux_t *m;
if (!c || !c->avcc || !c->avcc_size || c->avcc_size > 65536
|| !c->max_packet_size || c->max_packet_size > 0xfffff7)
return NULL;
while (at < c->avcc_size)
{
if (!flv_annexb((const uint8_t*)c->avcc, c->avcc_size, &at, &nal, &size)
|| size < 3 || size > 65535 || (nal[0] & 0x81) || nal[1] != 1)
return NULL;
type = (nal[0] >> 1) & 63;
if (type < 32 || type > 34 || sets[type - 32] || size > 65536 - total)
return NULL;
sets[type - 32] = nal;
lengths[type - 32] = size;
total += size;
}
if (!sets[0] || !sets[1] || !sets[2])
return NULL;
hvcc = (uint8_t*)calloc(1, total);
if (!hvcc)
return NULL;
if (!flv_hevc_info(sets[1], lengths[1], hvcc))
{
free(hvcc);
return NULL;
}
at = 23;
for (i = 0; i < 3; i++)
{
hvcc[at++] = (uint8_t)(0xa0 + i);
flv_uint(hvcc + at, 1, 2);
flv_uint(hvcc + at + 2, (uint32_t)lengths[i], 2);
memcpy(hvcc + at + 4, sets[i], lengths[i]);
at += lengths[i] + 4;
}
config = *c;
config.avcc = hvcc;
config.avcc_size = total;
m = rflv_mux_new_hevc(&config);
free(hvcc);
if (!m)
return NULL;
m->converted = (uint8_t*)malloc(m->limit);
if (!m->converted)
{
rflv_mux_free(m);
return NULL;
}
return m;
}
rflv_mux_t *rflv_mux_new_annexb(const rflv_config_t *c)
{
rflv_config_t config;
rflv_mux_t *m;
const uint8_t *nal, *sps = NULL, *pps = NULL;
uint8_t *avcc;
size_t offset = 0, size, sps_size = 0, pps_size = 0;
if (!c || !c->avcc || !c->avcc_size || c->avcc_size > 65536
|| !c->max_packet_size || c->max_packet_size > 0xfffffa)
return NULL;
while (offset < c->avcc_size)
{
unsigned type;
if (!flv_annexb((const uint8_t*)c->avcc, c->avcc_size, &offset, &nal, &size)
|| size > 65535 || (nal[0] & 0x80))
return NULL;
type = nal[0] & 31;
if (type == 7 && !sps && size >= 4)
{
sps = nal;
sps_size = size;
}
else if (type == 8 && !pps)
{
pps = nal;
pps_size = size;
}
else
return NULL;
}
if (!sps || !pps || sps_size + pps_size > 65536 - 11)
return NULL;
size = sps_size + pps_size + 11;
avcc = (uint8_t*)malloc(size);
if (!avcc)
return NULL;
avcc[0] = 1;
memcpy(avcc + 1, sps + 1, 3);
avcc[4] = 255;
avcc[5] = 225;
flv_uint(avcc + 6, (uint32_t)sps_size, 2);
memcpy(avcc + 8, sps, sps_size);
avcc[8 + sps_size] = 1;
flv_uint(avcc + 9 + sps_size, (uint32_t)pps_size, 2);
memcpy(avcc + 11 + sps_size, pps, pps_size);
config = *c;
config.avcc = avcc;
config.avcc_size = size;
m = rflv_mux_new(&config);
free(avcc);
if (!m)
return NULL;
m->converted = (uint8_t*)malloc(m->limit);
if (!m->converted)
{
rflv_mux_free(m);
return NULL;
}
return m;
}
static bool flv_milliseconds(uint64_t ticks, unsigned scale, uint32_t *result)
{
uint64_t seconds = ticks / scale;
@@ -785,7 +209,6 @@ int rflv_mux_push(rflv_mux_t *m, unsigned track, const void *data,
return RFLV_ERROR;
composition = (int64_t)pts_ms - dts_ms;
if ((track == 1 && (composition < -0x800000 || composition > 0x7fffff
|| (m->av1 && pts != dts)
|| (!m->seen[0] && !keyframe))) || (track == 2 && pts != dts))
return RFLV_ERROR;
m->track = track;
@@ -797,8 +220,6 @@ int rflv_mux_push(rflv_mux_t *m, unsigned track, const void *data,
m->composition = (int32_t)composition;
m->keyframe = keyframe;
m->vcl = m->idr = false;
m->annexb = false;
m->converted_size = 0;
m->output = FLV_MEDIA;
m->scanning = track == 1;
if (track == 2)
@@ -806,22 +227,8 @@ int rflv_mux_push(rflv_mux_t *m, unsigned track, const void *data,
return RFLV_PROGRESS;
}
int rflv_mux_push_annexb(rflv_mux_t *m, const void *data, size_t size,
uint64_t dts, uint64_t pts, bool keyframe)
{
int result;
if (!m || !m->converted)
return RFLV_ERROR;
result = rflv_mux_push(m, 1, data, size, dts, pts, keyframe);
if (result == RFLV_PROGRESS)
m->annexb = true;
return result;
}
int rflv_mux_step(rflv_mux_t *m)
{
const uint8_t *nal;
size_t size;
uint32_t length;
unsigned type;
if (!m || m->failed)
@@ -837,70 +244,22 @@ int rflv_mux_step(rflv_mux_t *m)
if (!m->vcl || (!m->seen[0] && !m->idr))
goto failed;
m->scanning = false;
flv_tag(m, 1, m->annexb ? m->converted : m->input,
m->annexb ? m->converted_size : m->size,
m->timestamp, m->composition, m->keyframe, false);
flv_tag(m, 1, m->input, m->size, m->timestamp, m->composition, m->keyframe, false);
return RFLV_PACKET;
}
if (m->av1)
{
rav1_obu_t obu;
if (rav1_obu_next(&obu, m->input, m->size, &m->offset, false) != 1
|| !obu.type || (obu.type >= 8 && obu.type != 15)
|| obu.spatial_id)
goto failed;
if (obu.type == 1 && (obu.payload_size != m->av1_config.sequence.payload_size
|| memcmp(obu.payload, m->av1_config.sequence.payload, obu.payload_size)))
goto failed;
if (obu.type == 3 || obu.type == 6)
{
if (!obu.payload_size)
goto failed;
m->vcl = true;
m->idr = m->idr || m->av1_sequence->reduced_still_picture_header
|| (obu.payload[0] & 0xe0) == 0;
}
return RFLV_PROGRESS;
}
if (m->annexb)
{
if (!flv_annexb(m->input, m->size, &m->offset, &nal, &size)
|| m->limit - m->converted_size < 4
|| size > m->limit - m->converted_size - 4)
goto failed;
flv_uint(m->converted + m->converted_size, (uint32_t)size, 4);
memcpy(m->converted + m->converted_size + 4, nal, size);
m->converted_size += size + 4;
}
else
{
if (m->size - m->offset < 4)
goto failed;
length = ((uint32_t)m->input[m->offset] << 24) | ((uint32_t)m->input[m->offset + 1] << 16)
| ((uint32_t)m->input[m->offset + 2] << 8) | m->input[m->offset + 3];
m->offset += 4;
if (!length || length > m->size - m->offset)
goto failed;
nal = m->input + m->offset;
size = length;
m->offset += length;
}
if (nal[0] & 0x80)
if (m->size - m->offset < 4)
goto failed;
if (m->hevc)
{
if (size < 2 || !(nal[1] & 7))
goto failed;
type = (nal[0] >> 1) & 63;
m->vcl = m->vcl || type <= 31;
m->idr = m->idr || (type >= 16 && type <= 23);
return RFLV_PROGRESS;
}
type = nal[0] & 31;
length = ((uint32_t)m->input[m->offset] << 24) | ((uint32_t)m->input[m->offset + 1] << 16)
| ((uint32_t)m->input[m->offset + 2] << 8) | m->input[m->offset + 3];
m->offset += 4;
if (!length || length > m->size - m->offset || (m->input[m->offset] & 0x80))
goto failed;
type = m->input[m->offset] & 31;
if (!type || type >= 24)
goto failed;
m->vcl = m->vcl || type <= 5;
m->idr = m->idr || type == 5;
m->offset += length;
return RFLV_PROGRESS;
failed:
m->failed = true;
@@ -918,31 +277,12 @@ bool rflv_mux_get(rflv_mux_t *m, const rflv_span_t **spans, size_t *count)
return true;
}
bool rflv_mux_get_tag(rflv_mux_t *m, rflv_tag_t *tag)
{
if (!m || !tag || !m->pending || m->output == FLV_HEADER)
return false;
tag->spans[0].data = m->prefix + 11;
tag->spans[0].size = m->spans[0].size - 11;
tag->spans[1] = m->spans[1];
tag->timestamp = m->timestamp;
tag->type = m->prefix[0];
return true;
}
bool rflv_mux_release(rflv_mux_t *m)
{
if (!m || !m->pending)
return false;
m->pending = false;
if (m->output == FLV_HEADER && m->metadata)
{
m->output = FLV_COLOR;
flv_tag(m, 1, m->metadata, m->metadata_size, 0, 0, true, true);
/* Information-frame flags preserve existing demuxer interoperability. */
m->prefix[11] = 0xd4;
}
else if ((m->output == FLV_HEADER || m->output == FLV_COLOR) && m->avcc_size)
if (m->output == FLV_HEADER && m->avcc_size)
{
m->output = FLV_VIDEO_CONFIG;
flv_tag(m, 1, m->config, m->avcc_size, 0, 0, true, true);
@@ -979,8 +319,5 @@ void rflv_mux_free(rflv_mux_t *m)
if (!m)
return;
free(m->config);
free(m->converted);
free(m->metadata);
free(m->av1_sequence);
free(m);
}
Loaded 100 of 560 files, more files were not shown because too many files have changed in this diff. Show more