Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
122 changes: 114 additions & 8 deletions .github/workflows/c-cpp.yml
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,13 @@ jobs:
cc: 'clang'
cxx: 'clang++'

# Windows
- displayTargetName: 'macOS x86_64 (Clang)'
artifact: 'virtualjaguar_libretro.dylib'
os: macos-13
cc: 'clang'
cxx: 'clang++'

# Windows (MinGW)
- displayTargetName: 'Windows x86_64 (MSYS2)'
artifact: 'virtualjaguar_libretro.dll'
os: windows-latest
Expand All @@ -71,28 +77,38 @@ jobs:
os: ubuntu-latest
emscripten: true

# Android NDK (arm64-v8a)
# Android NDK
- displayTargetName: 'Android arm64-v8a'
artifact: 'libs/arm64-v8a/libretro.so'
os: ubuntu-latest
android: true
android_abi: 'arm64-v8a'

# Android NDK (armeabi-v7a)
- displayTargetName: 'Android armeabi-v7a'
artifact: 'libs/armeabi-v7a/libretro.so'
os: ubuntu-latest
android: true
android_abi: 'armeabi-v7a'

# iOS
- displayTargetName: 'Android x86_64'
artifact: 'libs/x86_64/libretro.so'
os: ubuntu-latest
android: true
android_abi: 'x86_64'

- displayTargetName: 'Android x86'
artifact: 'libs/x86/libretro.so'
os: ubuntu-latest
android: true
android_abi: 'x86'

# iOS / tvOS
- displayTargetName: 'iOS arm64'
artifact: 'virtualjaguar_libretro_ios.dylib'
os: macos-latest
make_platform: 'ios-arm64'
cross: true

# tvOS
- displayTargetName: 'tvOS arm64'
artifact: 'virtualjaguar_libretro_tvos.dylib'
os: macos-latest
Expand Down Expand Up @@ -181,6 +197,79 @@ jobs:
path: ${{ matrix.config.artifact }}
if-no-files-found: error

msvc-check:
name: MSVC ${{ matrix.arch }} compilation check
runs-on: windows-latest
strategy:
fail-fast: false
matrix:
arch: [x64, x86]
steps:
- uses: actions/checkout@v4

- uses: ilammy/msvc-dev-cmd@v1
with:
arch: ${{ matrix.arch }}

- name: Compile all sources with cl.exe
shell: cmd
run: |
cl.exe /c /W3 /O2 /DNDEBUG /D_CRT_SECURE_NO_DEPRECATE ^
/I. /Isrc /Isrc\m68000 /Ilibretro-common\include ^
/D__LIBRETRO__ /DINLINE="_inline" ^
libretro.c ^
src\blitter.c src\dac.c src\dsp.c src\file.c ^
src\gpu.c src\jaguar.c src\jerry.c src\tom.c src\op.c ^
src\cdintf.c src\cdrom.c src\crc32.c src\event.c ^
src\eeprom.c src\filedb.c src\joystick.c src\settings.c ^
src\memtrack.c src\mmu.c src\vjag_memory.c ^
src\universalhdr.c src\wavetable.c ^
src\jagbios.c src\jagbios2.c ^
src\jagcdbios.c src\jagdevcdbios.c ^
src\jagstub1bios.c src\jagstub2bios.c ^
src\m68000\m68kinterface.c ^
src\blitter_simd_scalar.c ^
src\blitter_simd_sse2.c
echo MSVC compilation check passed

vita-build:
name: build-PS Vita
runs-on: ubuntu-latest
container:
image: vitasdk/vitasdk:latest
steps:
- uses: actions/checkout@v4

- name: Build
run: make -j4 platform=vita

- name: Upload artifact
uses: actions/upload-artifact@v4
with:
name: PS Vita
path: virtualjaguar_libretro_vita.a
if-no-files-found: error

switch-build:
name: build-Nintendo Switch
runs-on: ubuntu-latest
container:
image: devkitpro/devkita64:latest
steps:
- uses: actions/checkout@v4

- name: Build
run: make -j4 platform=libnx
env:
DEVKITPRO: /opt/devkitpro

- name: Upload artifact
uses: actions/upload-artifact@v4
with:
name: Nintendo Switch
path: virtualjaguar_libretro_libnx.a
if-no-files-found: error

c89-lint:
name: C89 compliance check
runs-on: ubuntu-latest
Expand All @@ -191,10 +280,9 @@ jobs:
run: |
echo "==> Checking C89 compliance (catches MSVC C89 errors)..."
FAILED=0
for f in libretro.c src/*.c; do
# Skip machine-generated files
for f in libretro.c src/*.c src/m68000/m68kinterface.c; do
case "$f" in
src/m68000/*|src/jag*bios*.c|src/jagstub*bios.c|src/blitter_simd_neon.c|src/blitter_simd_sse2.c) continue ;;
src/m68000/cpu*.c|src/m68000/read*.c|src/jag*bios*.c|src/jagstub*bios.c|src/blitter_simd_neon.c|src/blitter_simd_sse2.c) continue ;;
esac
if ! gcc -fsyntax-only -std=gnu89 \
-Werror=declaration-after-statement \
Expand All @@ -209,3 +297,21 @@ jobs:
exit 1
fi
echo "==> All files pass C89 declaration check"

- name: Check for stdbool.h usage (use boolean.h instead)
run: |
echo "==> Checking for direct stdbool.h includes..."
FAILED=0
for f in libretro.c src/*.c src/*.h; do
case "$f" in
src/boolean.h) continue ;;
esac
if grep -n '#include.*<stdbool\.h>' "$f" 2>/dev/null; then
echo "::error file=$f::Use <boolean.h> instead of <stdbool.h> (MSVC 2005/2010 compat)"
FAILED=1
fi
done
if [ "$FAILED" = "1" ]; then
exit 1
fi
echo "==> No direct stdbool.h includes found"
71 changes: 68 additions & 3 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,12 @@ jobs:
cc: clang
cxx: clang++

- platform: macos-x86_64
artifact: virtualjaguar_libretro.dylib
os: macos-13
cc: clang
cxx: clang++

# Windows
- platform: windows-x86_64
artifact: virtualjaguar_libretro.dll
Expand Down Expand Up @@ -78,13 +84,24 @@ jobs:
android: true
android_abi: 'armeabi-v7a'

# iOS
- platform: android-x86_64
artifact: libs/x86_64/libretro.so
os: ubuntu-latest
android: true
android_abi: 'x86_64'

- platform: android-x86
artifact: libs/x86/libretro.so
os: ubuntu-latest
android: true
android_abi: 'x86'

# iOS / tvOS
- platform: ios-arm64
artifact: virtualjaguar_libretro_ios.dylib
os: macos-latest
make_platform: 'ios-arm64'

# tvOS
- platform: tvos-arm64
artifact: virtualjaguar_libretro_tvos.dylib
os: macos-latest
Expand Down Expand Up @@ -156,8 +173,56 @@ jobs:
path: dist/
if-no-files-found: error

vita-build:
name: build-vita
runs-on: ubuntu-latest
container:
image: vitasdk/vitasdk:latest
steps:
- uses: actions/checkout@v4

- name: Build
run: make -j4 platform=vita

- name: Package
run: |
mkdir -p dist
cp virtualjaguar_libretro_vita.a dist/virtualjaguar_libretro-vita.a

- name: Upload artifact
uses: actions/upload-artifact@v4
with:
name: virtualjaguar_libretro-vita
path: dist/
if-no-files-found: error

switch-build:
name: build-switch
runs-on: ubuntu-latest
container:
image: devkitpro/devkita64:latest
steps:
- uses: actions/checkout@v4

- name: Build
run: make -j4 platform=libnx
env:
DEVKITPRO: /opt/devkitpro

- name: Package
run: |
mkdir -p dist
cp virtualjaguar_libretro_libnx.a dist/virtualjaguar_libretro-switch.a

- name: Upload artifact
uses: actions/upload-artifact@v4
with:
name: virtualjaguar_libretro-switch
path: dist/
if-no-files-found: error

release:
needs: build
needs: [build, vita-build, switch-build]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
Expand Down
2 changes: 1 addition & 1 deletion src/blitter_simd.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
#define BLITTER_SIMD_H

#include <stdint.h>
#include <stdbool.h>
#include <boolean.h>

typedef struct
{
Expand Down
39 changes: 23 additions & 16 deletions src/blitter_simd_sse2.c
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,16 @@
#include <emmintrin.h> /* SSE2 */
#include <string.h> /* memcpy for type-punning extract */

/* _mm_cvtsi128_si64 only exists on x86_64 (needs 64-bit GP register).
* memcpy from the __m128i is portable, alignment-safe, and compilers
* optimize it to a single register move. */
/* _mm_set_epi64x doesn't exist in MSVC 2010 and earlier.
* Build from two 32-bit halves instead (pure SSE2). */
#if defined(_MSC_VER) && _MSC_VER < 1700
#define SSE2_SET64(hi, lo) \
_mm_set_epi32((int)((uint64_t)(hi) >> 32), (int)(hi), \
(int)((uint64_t)(lo) >> 32), (int)(lo))
#else
#define SSE2_SET64(hi, lo) _mm_set_epi64x((int64_t)(hi), (int64_t)(lo))
#endif

static uint64_t sse2_extract_u64(__m128i v)
{
uint64_t r;
Expand All @@ -35,15 +42,15 @@ static uint64_t sse2_lfu(uint64_t srcd, uint64_t dstd, uint8_t lfu_func)
uint64_t func2 = (lfu_func & 0x04) ? 0xFFFFFFFFFFFFFFFFULL : 0;
uint64_t func3 = (lfu_func & 0x08) ? 0xFFFFFFFFFFFFFFFFULL : 0;

__m128i vs = _mm_set_epi64x(0, (int64_t)srcd);
__m128i vd = _mm_set_epi64x(0, (int64_t)dstd);
__m128i vs = SSE2_SET64(0, srcd);
__m128i vd = SSE2_SET64(0, dstd);
__m128i vns = _mm_andnot_si128(vs, _mm_set1_epi32(-1)); /* ~srcd */
__m128i vnd = _mm_andnot_si128(vd, _mm_set1_epi32(-1)); /* ~dstd */

__m128i vf0 = _mm_set_epi64x(0, (int64_t)func0);
__m128i vf1 = _mm_set_epi64x(0, (int64_t)func1);
__m128i vf2 = _mm_set_epi64x(0, (int64_t)func2);
__m128i vf3 = _mm_set_epi64x(0, (int64_t)func3);
__m128i vf0 = SSE2_SET64(0, func0);
__m128i vf1 = SSE2_SET64(0, func1);
__m128i vf2 = SSE2_SET64(0, func2);
__m128i vf3 = SSE2_SET64(0, func3);

/* (~s & ~d & f0) | (~s & d & f1) | (s & ~d & f2) | (s & d & f3) */
__m128i t0 = _mm_and_si128(_mm_and_si128(vns, vnd), vf0);
Expand All @@ -64,8 +71,8 @@ static uint64_t sse2_lfu(uint64_t srcd, uint64_t dstd, uint8_t lfu_func)
static uint8_t sse2_dcomp(uint64_t patd, uint64_t srcd, uint64_t dstd, bool cmpdst)
{
uint64_t other = cmpdst ? dstd : srcd;
__m128i vp = _mm_set_epi64x(0, (int64_t)patd);
__m128i vo = _mm_set_epi64x(0, (int64_t)other);
__m128i vp = SSE2_SET64(0, patd);
__m128i vo = SSE2_SET64(0, other);
__m128i vxor = _mm_xor_si128(vp, vo);

/* Compare each byte against zero */
Expand All @@ -88,8 +95,8 @@ static uint8_t sse2_zcomp(uint64_t srcz, uint64_t dstz, uint8_t zmode)
uint8_t result = 0;
uint8_t packed = 0;

__m128i vs = _mm_set_epi64x(0, (int64_t)srcz);
__m128i vd = _mm_set_epi64x(0, (int64_t)dstz);
__m128i vs = SSE2_SET64(0, srcz);
__m128i vd = SSE2_SET64(0, dstz);

/* Bias for unsigned comparison via signed instructions */
__m128i bias = _mm_set1_epi16((short)0x8000);
Expand Down Expand Up @@ -150,9 +157,9 @@ static uint64_t sse2_byte_merge(uint64_t src, uint64_t dst, uint16_t mask)
sel64 |= (uint64_t)((uint8_t)(-(int8_t)((mask >> 13) & 1))) << 48;
sel64 |= (uint64_t)((uint8_t)(-(int8_t)((mask >> 14) & 1))) << 56;

vmask = _mm_set_epi64x(0, (int64_t)sel64);
vsrc = _mm_set_epi64x(0, (int64_t)src);
vdst = _mm_set_epi64x(0, (int64_t)dst);
vmask = SSE2_SET64(0, sel64);
vsrc = SSE2_SET64(0, src);
vdst = SSE2_SET64(0, dst);

/* result = (src & mask) | (dst & ~mask) */
r = _mm_or_si128(
Expand Down
2 changes: 1 addition & 1 deletion src/eeprom.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
#include "eeprom.h"

#include <stdlib.h>
#include <stdbool.h>
#include <boolean.h>
#include <string.h> // For memset

uint16_t eeprom_ram[64];
Expand Down
Loading
Loading