From 6c6531cba4c06324bb309bd3ed8e7551be1cc3fe Mon Sep 17 00:00:00 2001 From: Toad King Date: Fri, 26 Oct 2012 15:46:29 -0400 Subject: initial Android support --- jni/Android.mk | 104 ++++++++++++++++++++++++++++++++++++++++++++++ jni/Application.mk | 1 + libpcsxcore/gte_nf.c | 2 + libpcsxcore/plugins.c | 1 + plugins/cdrcimg/cdrcimg.c | 1 - 5 files changed, 108 insertions(+), 1 deletion(-) create mode 100644 jni/Android.mk create mode 100644 jni/Application.mk create mode 100644 libpcsxcore/gte_nf.c diff --git a/jni/Android.mk b/jni/Android.mk new file mode 100644 index 0000000..6be42b1 --- /dev/null +++ b/jni/Android.mk @@ -0,0 +1,104 @@ +LOCAL_PATH := $(call my-dir) + +include $(CLEAR_VARS) + +APP_DIR := ../../src + +ifneq ($(TARGET_ARCH_ABI),armeabi-v7a) + NO_NEON_BUILD := 1 +else + NO_NEON_BUILD := $(NO_NEON) +endif + +ifeq ($(NO_NEON_BUILD)$(TARGET_ARCH_ABI),1armeabi-v7a) + LOCAL_MODULE := retro-noneon +else + LOCAL_MODULE := retro +endif + +ifeq ($(TARGET_ARCH),arm) + LOCAL_ARM_MODE := arm + + ifeq ($(TARGET_ARCH_EABI),armeabi-v7a) + LOCAL_CFLAGS += -DHAVE_ARMV7=1 + else + LOCAL_CFLAGS += -DHAVE_ARMV7=0 + endif + + LOCAL_CFLAGS += -DANDROID_ARM + + LOCAL_SRC_FILES += ../libpcsxcore/gte_arm.S + + # dynarec + LOCAL_SRC_FILES += ../libpcsxcore/new_dynarec/new_dynarec.c ../libpcsxcore/new_dynarec/linkage_arm.S ../libpcsxcore/new_dynarec/emu_if.c ../libpcsxcore/new_dynarec/pcsxmem.c + + # spu + LOCAL_SRC_FILES += ../plugins/dfsound/arm_utils.S + + ifeq ($(NO_NEON_BUILD),1) + # gpu + LOCAL_CFLAGS += -DREARMED + LOCAL_SRC_FILES += ../plugins/gpulib/cspace.c ../plugins/gpu_unai/gpulib_if.cpp ../plugins/gpu_unai/gpu_arm.s + else + LOCAL_ARM_NEON := true + LOCAL_CFLAGS += -DNEON_BUILD -DTEXTURE_CACHE_4BPP -DTEXTURE_CACHE_8BPP + LOCAL_SRC_FILES += ../libpcsxcore/gte_neon.S ../plugins/gpulib/cspace_neon.s + + # gpu + LOCAL_SRC_FILES += ../plugins/gpu_neon/psx_gpu_if.c ../plugins/gpu_neon/psx_gpu/psx_gpu_arm_neon.S + endif +endif + +ifeq ($(TARGET_ARCH),x86) + LOCAL_CFLAGS += -DANDROID_X86 +endif + +ifeq ($(TARGET_ARCH),mips) + LOCAL_CFLAGS += -DANDROID_MIPS -D__mips__ -D__MIPSEL__ +endif + +ifneq ($(TARGET_ARCH),arm) + # gpu + LOCAL_CFLAGS += -DREARMED + LOCAL_SRC_FILES += ../plugins/gpulib/cspace.c ../plugins/gpu_unai/gpulib_if.cpp +endif + +$(shell cd "$(LOCAL_PATH)" && ((git describe || echo) | sed -e 's/.*/#define REV "\0"/' > ../frontend/revision.h_)) +$(shell cd "$(LOCAL_PATH)" && (diff -q ../frontend/revision.h_ ../frontend/revision.h > /dev/null 2>&1 || cp ../frontend/revision.h_ ../frontend/revision.h)) +$(shell cd "$(LOCAL_PATH)" && (rm ../frontend/revision.h_)) + +LOCAL_SRC_FILES += ../libpcsxcore/cdriso.c ../libpcsxcore/cdrom.c ../libpcsxcore/cheat.c ../libpcsxcore/debug.c \ + ../libpcsxcore/decode_xa.c ../libpcsxcore/disr3000a.c ../libpcsxcore/mdec.c \ + ../libpcsxcore/misc.c ../libpcsxcore/plugins.c ../libpcsxcore/ppf.c ../libpcsxcore/psxbios.c \ + ../libpcsxcore/psxcommon.c ../libpcsxcore/psxcounters.c ../libpcsxcore/psxdma.c ../libpcsxcore/psxhle.c \ + ../libpcsxcore/psxhw.c ../libpcsxcore/psxinterpreter.c ../libpcsxcore/psxmem.c ../libpcsxcore/r3000a.c \ + ../libpcsxcore/sio.c ../libpcsxcore/socket.c ../libpcsxcore/spu.c +LOCAL_SRC_FILES += ../libpcsxcore/gte.c ../libpcsxcore/gte_nf.c ../libpcsxcore/gte_divider.c + +# spu +LOCAL_SRC_FILES += ../plugins/dfsound/dma.c ../plugins/dfsound/freeze.c \ + ../plugins/dfsound/registers.c ../plugins/dfsound/spu.c \ + ../plugins/dfsound/out.c ../plugins/dfsound/nullsnd.c + +# builtin gpu +LOCAL_SRC_FILES += ../plugins/gpulib/gpu.c ../plugins/gpulib/vout_pl.c + +# cdrcimg +LOCAL_SRC_FILES += ../plugins/cdrcimg/cdrcimg.c + +# dfinput +LOCAL_SRC_FILES += ../plugins/dfinput/main.c ../plugins/dfinput/pad.c ../plugins/dfinput/guncon.c + +# gui +LOCAL_SRC_FILES += ../frontend/main.c ../frontend/plugin.c +LOCAL_SRC_FILES += ../frontend/common/fonts.c +LOCAL_SRC_FILES += ../frontend/linux/plat.c + +# libretro +LOCAL_SRC_FILES += ../frontend/libretro.c + +LOCAL_CFLAGS += -O3 -ffast-math -funroll-loops -DNDEBUG -D_FILE_OFFSET_BITS=64 -DHAVE_LIBRETRO -DNO_FRONTEND +LOCAL_C_INCLUDES += $(LOCAL_PATH)/../frontend +LOCAL_LDLIBS := -lz -llog + +include $(BUILD_SHARED_LIBRARY) diff --git a/jni/Application.mk b/jni/Application.mk new file mode 100644 index 0000000..f05229c --- /dev/null +++ b/jni/Application.mk @@ -0,0 +1 @@ +APP_ABI := armeabi armeabi-v7a diff --git a/libpcsxcore/gte_nf.c b/libpcsxcore/gte_nf.c new file mode 100644 index 0000000..177cd48 --- /dev/null +++ b/libpcsxcore/gte_nf.c @@ -0,0 +1,2 @@ +#define FLAGLESS +#include "gte.c" diff --git a/libpcsxcore/plugins.c b/libpcsxcore/plugins.c index 57e7ef2..57078ba 100644 --- a/libpcsxcore/plugins.c +++ b/libpcsxcore/plugins.c @@ -702,6 +702,7 @@ int LoadPlugins() { char Plugin[MAXPATHLEN]; ReleasePlugins(); + SysLibError(); if (UsingIso()) { LoadCDRplugin(NULL); diff --git a/plugins/cdrcimg/cdrcimg.c b/plugins/cdrcimg/cdrcimg.c index e327500..cf55073 100644 --- a/plugins/cdrcimg/cdrcimg.c +++ b/plugins/cdrcimg/cdrcimg.c @@ -12,7 +12,6 @@ #include #include #include -#include #include #include "cdrcimg.h" -- cgit v1.2.3 From f4ea2656730fa58df5d340f367ba2a334295c2eb Mon Sep 17 00:00:00 2001 From: twinaphex Date: Fri, 26 Oct 2012 22:08:27 +0200 Subject: (Android) renamed gte_arm.s to gte_arm.S so it builds on Linux --- libpcsxcore/gte_arm.S | 590 ++++++++++++++++++++++++++++++++++++++++++++++++++ libpcsxcore/gte_arm.s | 590 -------------------------------------------------- 2 files changed, 590 insertions(+), 590 deletions(-) create mode 100644 libpcsxcore/gte_arm.S delete mode 100644 libpcsxcore/gte_arm.s diff --git a/libpcsxcore/gte_arm.S b/libpcsxcore/gte_arm.S new file mode 100644 index 0000000..8700f69 --- /dev/null +++ b/libpcsxcore/gte_arm.S @@ -0,0 +1,590 @@ +/* + * (C) Gražvydas "notaz" Ignotas, 2011 + * + * This work is licensed under the terms of GNU GPL version 2 or later. + * See the COPYING file in the top-level directory. + */ + +/* .equiv HAVE_ARMV7, 1 */ + +.text +.align 2 + +.macro sgnxt16 rd rs +.if HAVE_ARMV7 + sxth \rd, \rs +.else + lsl \rd, \rs, #16 + asr \rd, \rd, #16 +.endif +.endm + +@ prepare work reg for ssatx +@ in: wr reg, bit to saturate to +.macro ssatx_prep wr bit +.if !HAVE_ARMV7 + mov \wr, #(1<<(\bit-1)) +.endif +.endm + +.macro ssatx rd wr bit +.if HAVE_ARMV7 + ssat \rd, #\bit, \rd +.else + cmp \rd, \wr + subge \rd, \wr, #1 + cmn \rd, \wr + rsblt \rd, \wr, #0 +.endif +.endm + +@ prepare work reg for ssatx0 (sat to 0..2^(bit-1)) +@ in: wr reg, bit to saturate to +.macro ssatx0_prep wr bit + mov \wr, #(1<<(\bit-1)) +.endm + +.macro ssatx0 rd wr bit + cmp \rd, \wr + subge \rd, \wr, #1 + cmn \rd, #0 + movlt \rd, #0 +.endm + +.macro usat16_ rd rs +.if HAVE_ARMV7 + usat \rd, #16, \rs +.else + subs \rd, \rs, #0 + movlt \rd, #0 + cmp \rd, #0x10000 + movge \rd, #0x0ff00 + orrge \rd, #0x000ff +.endif +.endm + +.macro udiv_ rd rm rs + lsl \rm, #16 + clz \rd, \rs + lsl \rs, \rs, \rd @ shift up divisor + orr \rd, \rd, #1<<31 + lsr \rd, \rd, \rd +0: + cmp \rm, \rs + subcs \rm, \rs + adcs \rd, \rd, \rd + lsr \rs, #1 + bcc 0b +.endm + +.macro newton_step rcp den zero t1 t2 + umull \t2, \t1, \den, \rcp @ \t2 is dummy + sub \t1, \zero, \t1, lsl #2 + smlal \t2, \rcp, \t1, \rcp +.endm + +.macro udiv_newton rd rm rs t1 t2 t3 t4 + lsl \rd, \rm, #16 + clz \t1, \rs + mov \t2, #0 + lsl \rs, \t1 @ normalize for the algo + mov \rm, #0x4d000000 @ initial estimate ~1.2 + + newton_step \rm, \rs, \t2, \t3, \t4 + newton_step \rm, \rs, \t2, \t3, \t4 + newton_step \rm, \rs, \t2, \t3, \t4 + newton_step \rm, \rs, \t2, \t3, \t4 + + umull \t4, \rd, \rm, \rd + rsb \t2, \t1, #30 @ here t1 is 1..15 + mov \rd, \rd, lsr \t2 +.endm + +@ unsigned divide rd = rm / rs; 16.16 result +@ no div by 0 check +@ in: rm, rs +@ trash: rm rs t* +.macro udiv rd rm rs t1 t2 t3 t4 + @udiv_ \rd, \rm, \rs + udiv_newton \rd, \rm, \rs, \t1, \t2, \t3, \t4 +.endm + +@ calculate RTPS/RTPT MAC values +@ in: r0 context, r8,r9 VXYZ +@ out: r10-r12 MAC123 +@ trash: r1-r7 +.macro do_rtpx_mac + add r1, r0, #4*32 + add r2, r0, #4*(32+5) @ gteTRX + ldmia r1!,{r5-r7} @ gteR1*,gteR2* + ldmia r2, {r10-r12} + smulbb r2, r5, r8 @ gteR11 * gteVX0 + smultt r3, r5, r8 @ gteR12 * gteVY0 + smulbb r4, r6, r9 @ gteR13 * gteVZ0 + qadd r2, r2, r3 + asr r4, r4, #1 @ prevent oflow, lose a bit + add r3, r4, r2, asr #1 + add r10,r10,r3, asr #11 @ gteMAC1 + smultb r2, r6, r8 @ gteR21 * gteVX0 + smulbt r3, r7, r8 @ gteR22 * gteVY0 + smultb r4, r7, r9 @ gteR23 * gteVZ0 + ldmia r1!,{r5-r6} @ gteR3* + qadd r2, r2, r3 + asr r4, r4, #1 + add r3, r4, r2, asr #1 + add r11,r11,r3, asr #11 @ gteMAC2 + @ be more accurate for gteMAC3, since it's also a divider + smulbb r2, r5, r8 @ gteR31 * gteVX0 + smultt r3, r5, r8 @ gteR32 * gteVY0 + smulbb r4, r6, r9 @ gteR33 * gteVZ0 + qadd r2, r2, r3 + asr r3, r4, #31 @ expand to 64bit + adds r1, r2, r4 + adc r3, r2, asr #31 @ 64bit sum in r3,r1 + add r12,r12,r3, lsl #20 + add r12,r12,r1, lsr #12 @ gteMAC3 +.endm + + +.global gteRTPS_nf_arm @ r0=CP2 (d,c), +gteRTPS_nf_arm: + push {r4-r11,lr} + + ldmia r0, {r8,r9} @ VXYZ(0) + do_rtpx_mac + add r1, r0, #4*25 @ gteMAC1 + add r2, r0, #4*17 @ gteSZ1 + stmia r1, {r10-r12} @ gteMAC123 save + ldmia r2, {r3-r5} + add r1, r0, #4*16 @ gteSZ0 + add r2, r0, #4*9 @ gteIR1 + ssatx_prep r6, 16 + usat16_ lr, r12 @ limD + ssatx r10,r6, 16 + ssatx r11,r6, 16 + ssatx r12,r6, 16 + stmia r1, {r3-r5,lr} @ gteSZ* + ldr r3, [r0,#4*(32+26)] @ gteH + stmia r2, {r10,r11,r12} @ gteIR123 save + cmp r3, lr, lsl #1 @ gteH < gteSZ3*2 ? + mov r9, #1<<30 + bhs 1f +.if 1 + udiv r9, r3, lr, r1, r2, r6, r7 +.else + push {r0, r12} + mov r0, r3 + mov r1, lr + bl DIVIDE + mov r9, r0 + pop {r0, r12} +.endif +1: + ldrd r6, [r0,#4*(32+24)] @ gteOFXY + cmp r9, #0x20000 + add r1, r0, #4*12 @ gteSXY0 + movhs r9, #0x20000 + ldmia r1, {r2-r4} + /* quotient */ subhs r9, #1 + mov r2, r6, asr #31 + smlal r6, r2, r10, r9 + stmia r1!,{r3,r4} @ shift gteSXY + mov r3, r7, asr #31 + smlal r7, r3, r11, r9 + lsr r6, #16 + /* gteDQA, gteDQB */ ldrd r10,[r0, #4*(32+27)] + orr r6, r2, lsl #16 @ (gteOFX + gteIR1 * q) >> 16 + ssatx_prep r2, 11 + lsr r7, #16 + /* gteDQB + gteDQA * q */ mla r4, r10, r9, r11 + orr r7, r3, lsl #16 @ (gteOFY + gteIR2 * q) >> 16 + ssatx r6, r2, 11 @ gteSX2 + ssatx r7, r2, 11 @ gteSY2 + strh r6, [r1] + strh r7, [r1, #2] + str r4, [r0,#4*24] @ gteMAC0 + asrs r4, #12 + movmi r4, #0 + cmp r4, #0x1000 @ limH + movgt r4, #0x1000 + str r4, [r0,#4*8] @ gteIR0 + + pop {r4-r11,pc} + .size gteRTPS_nf_arm, .-gteRTPS_nf_arm + + +.global gteRTPT_nf_arm @ r0=CP2 (d,c), +gteRTPT_nf_arm: + ldr r1, [r0, #4*19] @ gteSZ3 + push {r4-r11,lr} + str r1, [r0, #4*16] @ gteSZ0 + mov lr, #0 + +rtpt_arm_loop: + add r1, r0, lr, lsl #1 + ldrd r8, [r1] @ VXYZ(v) + do_rtpx_mac + + ssatx_prep r6, 16 + usat16_ r2, r12 @ limD + add r1, r0, #4*25 @ gteMAC1 + ldr r3, [r0,#4*(32+26)] @ gteH + stmia r1, {r10-r12} @ gteMAC123 save + add r1, r0, #4*17 + ssatx r10,r6, 16 + ssatx r11,r6, 16 + ssatx r12,r6, 16 + str r2, [r1, lr] @ fSZ(v) + cmp r3, r2, lsl #1 @ gteH < gteSZ3*2 ? + mov r9, #1<<30 + bhs 1f +.if 1 + udiv r9, r3, r2, r1, r4, r6, r7 +.else + push {r0, r12, lr} + mov r0, r3 + mov r1, r2 + bl DIVIDE + mov r9, r0 + pop {r0, r12, lr} +.endif +1: cmp r9, #0x20000 + add r1, r0, #4*12 + movhs r9, #0x20000 + ldrd r6, [r0,#4*(32+24)] @ gteOFXY + /* quotient */ subhs r9, #1 + mov r2, r6, asr #31 + smlal r6, r2, r10, r9 + mov r3, r7, asr #31 + smlal r7, r3, r11, r9 + lsr r6, #16 + orr r6, r2, lsl #16 @ (gteOFX + gteIR1 * q) >> 16 + ssatx_prep r2, 11 + lsr r7, #16 + orr r7, r3, lsl #16 @ (gteOFY + gteIR2 * q) >> 16 + ssatx r6, r2, 11 @ gteSX(v) + ssatx r7, r2, 11 @ gteSY(v) + strh r6, [r1, lr]! + add lr, #4 + strh r7, [r1, #2] + cmp lr, #12 + blt rtpt_arm_loop + + ldrd r4, [r0, #4*(32+27)] @ gteDQA, gteDQB + add r1, r0, #4*9 @ gteIR1 + mla r3, r4, r9, r5 @ gteDQB + gteDQA * q + stmia r1, {r10,r11,r12} @ gteIR123 save + + str r3, [r0,#4*24] @ gteMAC0 + asrs r3, #12 + movmi r3, #0 + cmp r3, #0x1000 @ limH + movgt r3, #0x1000 + str r3, [r0,#4*8] @ gteIR0 + + pop {r4-r11,pc} + .size gteRTPT_nf_arm, .-gteRTPT_nf_arm + + +@ note: not std calling convention used +@ r0 = CP2 (d,c) (must preserve) +@ r1 = needs_shift12 +@ r4,r5 = VXYZ(v) packed +@ r6 = &MX11(mx) +@ r7 = &CV1(cv) +.macro mvma_op do_flags + push {r8-r11} + +.if \do_flags + ands r3, r1, #1 @ gteFLAG, shift_need +.else + tst r1, #1 +.endif + ldmia r7, {r7-r9} @ CV123 + ldmia r6!,{r10-r12} @ MX1*,MX2* + asr r1, r7, #20 + lsl r7, #12 @ expand to 64bit + smlalbb r7, r1, r10, r4 @ MX11 * vx + smlaltt r7, r1, r10, r4 @ MX12 * vy + smlalbb r7, r1, r11, r5 @ MX13 * vz + lsrne r7, #12 + orrne r7, r1, lsl #20 @ gteMAC0 +.if \do_flags + asrne r1, #20 + adds r2, r7, #0x80000000 + adcs r1, #0 + orrgt r3, #(1<<30) + orrmi r3, #(1<<31)|(1<<27) + tst r3, #1 @ repeat shift test +.endif + asr r1, r8, #20 + lsl r8, #12 @ expand to 64bit + smlaltb r8, r1, r11, r4 @ MX21 * vx + smlalbt r8, r1, r12, r4 @ MX22 * vy + smlaltb r8, r1, r12, r5 @ MX23 * vz + lsrne r8, #12 + orrne r8, r1, lsl #20 @ gteMAC1 +.if \do_flags + asrne r1, #20 + adds r2, r8, #0x80000000 + adcs r1, #0 + orrgt r3, #(1<<29) + orrmi r3, #(1<<31)|(1<<26) + tst r3, #1 @ repeat shift test +.endif + ldmia r6!,{r10-r11} @ MX3* + asr r1, r9, #20 + lsl r9, #12 @ expand to 64bit + smlalbb r9, r1, r10, r4 @ MX31 * vx + smlaltt r9, r1, r10, r4 @ MX32 * vy + smlalbb r9, r1, r11, r5 @ MX33 * vz + lsrne r9, #12 + orrne r9, r1, lsl #20 @ gteMAC2 +.if \do_flags + asrne r1, #20 + adds r2, r9, #0x80000000 + adcs r1, #0 + orrgt r3, #(1<<28) + orrmi r3, #(1<<31)|(1<<25) + bic r3, #1 +.else + mov r3, #0 +.endif + str r3, [r0, #4*(32+31)] @ gteFLAG + add r1, r0, #4*25 + stmia r1, {r7-r9} + + pop {r8-r11} + bx lr +.endm + +.global gteMVMVA_part_arm +gteMVMVA_part_arm: + mvma_op 1 + .size gteMVMVA_part_arm, .-gteMVMVA_part_arm + +.global gteMVMVA_part_nf_arm +gteMVMVA_part_nf_arm: + mvma_op 0 + .size gteMVMVA_part_nf_arm, .-gteMVMVA_part_nf_arm + +@ common version of MVMVA with cv3 (== 0) and shift12, +@ can't overflow so no gteMAC flags needed +@ note: not std calling convention used +@ r0 = CP2 (d,c) (must preserve) +@ r4,r5 = VXYZ(v) packed +@ r6 = &MX11(mx) +.global gteMVMVA_part_cv3sh12_arm +gteMVMVA_part_cv3sh12_arm: + push {r8-r9} + ldmia r6!,{r7-r9} @ MX1*,MX2* + smulbb r1, r7, r4 @ MX11 * vx + smultt r2, r7, r4 @ MX12 * vy + smulbb r3, r8, r5 @ MX13 * vz + qadd r1, r1, r2 + asr r3, #1 @ prevent oflow, lose a bit + add r1, r3, r1, asr #1 + asr r7, r1, #11 + smultb r1, r8, r4 @ MX21 * vx + smulbt r2, r9, r4 @ MX22 * vy + smultb r3, r9, r5 @ MX23 * vz + qadd r1, r1, r2 + asr r3, #1 + add r1, r3, r1, asr #1 + asr r8, r1, #11 + ldmia r6, {r6,r9} @ MX3* + smulbb r1, r6, r4 @ MX31 * vx + smultt r2, r6, r4 @ MX32 * vy + smulbb r3, r9, r5 @ MX33 * vz + qadd r1, r1, r2 + asr r3, #1 + add r1, r3, r1, asr #1 + asr r9, r1, #11 + add r1, r0, #4*25 + mov r2, #0 + stmia r1, {r7-r9} + str r2, [r0, #4*(32+31)] @ gteFLAG + pop {r8-r9} + bx lr + .size gteMVMVA_part_cv3sh12_arm, .-gteMVMVA_part_cv3sh12_arm + + +.global gteNCLIP_arm @ r0=CP2 (d,c), +gteNCLIP_arm: + push {r4-r6,lr} + ldrsh r4, [r0, #4*12+2] + ldrsh r5, [r0, #4*13+2] + ldrsh r6, [r0, #4*14+2] + ldrsh lr, [r0, #4*12] + ldrsh r2, [r0, #4*13] + sub r12, r4, r5 @ 3: gteSY0 - gteSY1 + sub r5, r5, r6 @ 1: gteSY1 - gteSY2 + smull r1, r5, lr, r5 @ RdLo, RdHi + sub r6, r4 @ 2: gteSY2 - gteSY0 + ldrsh r3, [r0, #4*14] + smlal r1, r5, r2, r6 + mov lr, #0 @ gteFLAG + smlal r1, r5, r3, r12 + mov r6, #1<<31 + orr r6, #1<<15 + movs r2, r1, lsl #1 + adc r5, r5 + cmp r5, #0 +.if HAVE_ARMV7 + movtgt lr, #((1<<31)|(1<<16))>>16 +.else + movgt lr, #(1<<31) + orrgt lr, #(1<<16) +.endif + cmn r5, #1 + orrmi lr, r6 + str r1, [r0, #4*24] + str lr, [r0, #4*(32+31)] @ gteFLAG + + pop {r4-r6,pc} + .size gteNCLIP_arm, .-gteNCLIP_arm + + +.macro gteMACtoIR lm + ldr r2, [r0, #4*25] @ gteMAC1 + mov r1, #1<<15 + ldr r12,[r0, #4*(32+31)] @ gteFLAG + cmp r2, r1 + subge r2, r1, #1 + orrge r12, #(1<<31)|(1<<24) +.if \lm + cmp r2, #0 + movlt r2, #0 +.else + cmn r2, r1 + rsblt r2, r1, #0 +.endif + str r2, [r0, #4*9] + ldrd r2, [r0, #4*26] @ gteMAC23 + orrlt r12, #(1<<31)|(1<<24) + cmp r2, r1 + subge r2, r1, #1 + orrge r12, #1<<23 + orrge r12, #1<<31 +.if \lm + cmp r2, #0 + movlt r2, #0 +.else + cmn r2, r1 + rsblt r2, r1, #0 +.endif + orrlt r12, #1<<23 + orrlt r12, #1<<31 + cmp r3, r1 + subge r3, r1, #1 + orrge r12, #1<<22 +.if \lm + cmp r3, #0 + movlt r3, #0 +.else + cmn r3, r1 + rsblt r3, r1, #0 +.endif + orrlt r12, #1<<22 + strd r2, [r0, #4*10] @ gteIR23 + str r12,[r0, #4*(32+31)] @ gteFLAG + bx lr +.endm + +.global gteMACtoIR_lm0 @ r0=CP2 (d,c) +gteMACtoIR_lm0: + gteMACtoIR 0 + .size gteMACtoIR_lm0, .-gteMACtoIR_lm0 + +.global gteMACtoIR_lm1 @ r0=CP2 (d,c) +gteMACtoIR_lm1: + gteMACtoIR 1 + .size gteMACtoIR_lm1, .-gteMACtoIR_lm1 + + +.global gteMACtoIR_lm0_nf @ r0=CP2 (d,c) +gteMACtoIR_lm0_nf: + add r12, r0, #4*25 + ldmia r12, {r1-r3} + ssatx_prep r12, 16 + ssatx r1, r12, 16 + ssatx r2, r12, 16 + ssatx r3, r12, 16 + add r12, r0, #4*9 + stmia r12, {r1-r3} + bx lr + .size gteMACtoIR_lm0_nf, .-gteMACtoIR_lm0_nf + + +.global gteMACtoIR_lm1_nf @ r0=CP2 (d,c) +gteMACtoIR_lm1_nf: + add r12, r0, #4*25 + ldmia r12, {r1-r3} + ssatx0_prep r12, 16 + ssatx0 r1, r12, 16 + ssatx0 r2, r12, 16 + ssatx0 r3, r12, 16 + add r12, r0, #4*9 + stmia r12, {r1-r3} + bx lr + .size gteMACtoIR_lm1_nf, .-gteMACtoIR_lm1_nf + + +.if 0 +.global gteMVMVA_test +gteMVMVA_test: + push {r4-r7,lr} + push {r1} + and r2, r1, #0x18000 @ v + cmp r2, #0x18000 @ v == 3? + addeq r4, r0, #4*9 + addne r3, r0, r2, lsr #12 + ldmeqia r4, {r3-r5} + ldmneia r3, {r4,r5} + lsleq r3, #16 + lsreq r3, #16 + orreq r4, r3, r4, lsl #16 @ r4,r5 = VXYZ(v) + @and r5, #0xffff + add r12, r0, #4*32 + and r3, r1, #0x60000 @ mx + lsr r3, #17 + add r6, r12, r3, lsl #5 + cmp r3, #3 + adreq r6, zeroes + and r2, r1, #0x06000 @ cv + lsr r2, #13 + add r7, r12, r2, lsl #5 + add r7, #4*5 + cmp r2, #3 + adreq r7, zeroes +.if 1 + adr lr, 1f + bne 0f + tst r1, #1<<19 + bne gteMVMVA_part_cv3sh12_arm +0: + and r1, #1<<19 + lsr r1, #19 + b gteMVMVA_part_arm +1: + pop {r1} + tst r1, #1<<10 + adr lr, 0f + beq gteMACtoIR_lm0 + bne gteMACtoIR_lm1 +0: +.else + bl gteMVMVA_part_neon + pop {r1} + and r1, #1<<10 + bl gteMACtoIR_flags_neon +.endif + pop {r4-r7,pc} + +zeroes: + .word 0,0,0,0,0 +.endif + + +@ vim:filetype=armasm + diff --git a/libpcsxcore/gte_arm.s b/libpcsxcore/gte_arm.s deleted file mode 100644 index 8700f69..0000000 --- a/libpcsxcore/gte_arm.s +++ /dev/null @@ -1,590 +0,0 @@ -/* - * (C) Gražvydas "notaz" Ignotas, 2011 - * - * This work is licensed under the terms of GNU GPL version 2 or later. - * See the COPYING file in the top-level directory. - */ - -/* .equiv HAVE_ARMV7, 1 */ - -.text -.align 2 - -.macro sgnxt16 rd rs -.if HAVE_ARMV7 - sxth \rd, \rs -.else - lsl \rd, \rs, #16 - asr \rd, \rd, #16 -.endif -.endm - -@ prepare work reg for ssatx -@ in: wr reg, bit to saturate to -.macro ssatx_prep wr bit -.if !HAVE_ARMV7 - mov \wr, #(1<<(\bit-1)) -.endif -.endm - -.macro ssatx rd wr bit -.if HAVE_ARMV7 - ssat \rd, #\bit, \rd -.else - cmp \rd, \wr - subge \rd, \wr, #1 - cmn \rd, \wr - rsblt \rd, \wr, #0 -.endif -.endm - -@ prepare work reg for ssatx0 (sat to 0..2^(bit-1)) -@ in: wr reg, bit to saturate to -.macro ssatx0_prep wr bit - mov \wr, #(1<<(\bit-1)) -.endm - -.macro ssatx0 rd wr bit - cmp \rd, \wr - subge \rd, \wr, #1 - cmn \rd, #0 - movlt \rd, #0 -.endm - -.macro usat16_ rd rs -.if HAVE_ARMV7 - usat \rd, #16, \rs -.else - subs \rd, \rs, #0 - movlt \rd, #0 - cmp \rd, #0x10000 - movge \rd, #0x0ff00 - orrge \rd, #0x000ff -.endif -.endm - -.macro udiv_ rd rm rs - lsl \rm, #16 - clz \rd, \rs - lsl \rs, \rs, \rd @ shift up divisor - orr \rd, \rd, #1<<31 - lsr \rd, \rd, \rd -0: - cmp \rm, \rs - subcs \rm, \rs - adcs \rd, \rd, \rd - lsr \rs, #1 - bcc 0b -.endm - -.macro newton_step rcp den zero t1 t2 - umull \t2, \t1, \den, \rcp @ \t2 is dummy - sub \t1, \zero, \t1, lsl #2 - smlal \t2, \rcp, \t1, \rcp -.endm - -.macro udiv_newton rd rm rs t1 t2 t3 t4 - lsl \rd, \rm, #16 - clz \t1, \rs - mov \t2, #0 - lsl \rs, \t1 @ normalize for the algo - mov \rm, #0x4d000000 @ initial estimate ~1.2 - - newton_step \rm, \rs, \t2, \t3, \t4 - newton_step \rm, \rs, \t2, \t3, \t4 - newton_step \rm, \rs, \t2, \t3, \t4 - newton_step \rm, \rs, \t2, \t3, \t4 - - umull \t4, \rd, \rm, \rd - rsb \t2, \t1, #30 @ here t1 is 1..15 - mov \rd, \rd, lsr \t2 -.endm - -@ unsigned divide rd = rm / rs; 16.16 result -@ no div by 0 check -@ in: rm, rs -@ trash: rm rs t* -.macro udiv rd rm rs t1 t2 t3 t4 - @udiv_ \rd, \rm, \rs - udiv_newton \rd, \rm, \rs, \t1, \t2, \t3, \t4 -.endm - -@ calculate RTPS/RTPT MAC values -@ in: r0 context, r8,r9 VXYZ -@ out: r10-r12 MAC123 -@ trash: r1-r7 -.macro do_rtpx_mac - add r1, r0, #4*32 - add r2, r0, #4*(32+5) @ gteTRX - ldmia r1!,{r5-r7} @ gteR1*,gteR2* - ldmia r2, {r10-r12} - smulbb r2, r5, r8 @ gteR11 * gteVX0 - smultt r3, r5, r8 @ gteR12 * gteVY0 - smulbb r4, r6, r9 @ gteR13 * gteVZ0 - qadd r2, r2, r3 - asr r4, r4, #1 @ prevent oflow, lose a bit - add r3, r4, r2, asr #1 - add r10,r10,r3, asr #11 @ gteMAC1 - smultb r2, r6, r8 @ gteR21 * gteVX0 - smulbt r3, r7, r8 @ gteR22 * gteVY0 - smultb r4, r7, r9 @ gteR23 * gteVZ0 - ldmia r1!,{r5-r6} @ gteR3* - qadd r2, r2, r3 - asr r4, r4, #1 - add r3, r4, r2, asr #1 - add r11,r11,r3, asr #11 @ gteMAC2 - @ be more accurate for gteMAC3, since it's also a divider - smulbb r2, r5, r8 @ gteR31 * gteVX0 - smultt r3, r5, r8 @ gteR32 * gteVY0 - smulbb r4, r6, r9 @ gteR33 * gteVZ0 - qadd r2, r2, r3 - asr r3, r4, #31 @ expand to 64bit - adds r1, r2, r4 - adc r3, r2, asr #31 @ 64bit sum in r3,r1 - add r12,r12,r3, lsl #20 - add r12,r12,r1, lsr #12 @ gteMAC3 -.endm - - -.global gteRTPS_nf_arm @ r0=CP2 (d,c), -gteRTPS_nf_arm: - push {r4-r11,lr} - - ldmia r0, {r8,r9} @ VXYZ(0) - do_rtpx_mac - add r1, r0, #4*25 @ gteMAC1 - add r2, r0, #4*17 @ gteSZ1 - stmia r1, {r10-r12} @ gteMAC123 save - ldmia r2, {r3-r5} - add r1, r0, #4*16 @ gteSZ0 - add r2, r0, #4*9 @ gteIR1 - ssatx_prep r6, 16 - usat16_ lr, r12 @ limD - ssatx r10,r6, 16 - ssatx r11,r6, 16 - ssatx r12,r6, 16 - stmia r1, {r3-r5,lr} @ gteSZ* - ldr r3, [r0,#4*(32+26)] @ gteH - stmia r2, {r10,r11,r12} @ gteIR123 save - cmp r3, lr, lsl #1 @ gteH < gteSZ3*2 ? - mov r9, #1<<30 - bhs 1f -.if 1 - udiv r9, r3, lr, r1, r2, r6, r7 -.else - push {r0, r12} - mov r0, r3 - mov r1, lr - bl DIVIDE - mov r9, r0 - pop {r0, r12} -.endif -1: - ldrd r6, [r0,#4*(32+24)] @ gteOFXY - cmp r9, #0x20000 - add r1, r0, #4*12 @ gteSXY0 - movhs r9, #0x20000 - ldmia r1, {r2-r4} - /* quotient */ subhs r9, #1 - mov r2, r6, asr #31 - smlal r6, r2, r10, r9 - stmia r1!,{r3,r4} @ shift gteSXY - mov r3, r7, asr #31 - smlal r7, r3, r11, r9 - lsr r6, #16 - /* gteDQA, gteDQB */ ldrd r10,[r0, #4*(32+27)] - orr r6, r2, lsl #16 @ (gteOFX + gteIR1 * q) >> 16 - ssatx_prep r2, 11 - lsr r7, #16 - /* gteDQB + gteDQA * q */ mla r4, r10, r9, r11 - orr r7, r3, lsl #16 @ (gteOFY + gteIR2 * q) >> 16 - ssatx r6, r2, 11 @ gteSX2 - ssatx r7, r2, 11 @ gteSY2 - strh r6, [r1] - strh r7, [r1, #2] - str r4, [r0,#4*24] @ gteMAC0 - asrs r4, #12 - movmi r4, #0 - cmp r4, #0x1000 @ limH - movgt r4, #0x1000 - str r4, [r0,#4*8] @ gteIR0 - - pop {r4-r11,pc} - .size gteRTPS_nf_arm, .-gteRTPS_nf_arm - - -.global gteRTPT_nf_arm @ r0=CP2 (d,c), -gteRTPT_nf_arm: - ldr r1, [r0, #4*19] @ gteSZ3 - push {r4-r11,lr} - str r1, [r0, #4*16] @ gteSZ0 - mov lr, #0 - -rtpt_arm_loop: - add r1, r0, lr, lsl #1 - ldrd r8, [r1] @ VXYZ(v) - do_rtpx_mac - - ssatx_prep r6, 16 - usat16_ r2, r12 @ limD - add r1, r0, #4*25 @ gteMAC1 - ldr r3, [r0,#4*(32+26)] @ gteH - stmia r1, {r10-r12} @ gteMAC123 save - add r1, r0, #4*17 - ssatx r10,r6, 16 - ssatx r11,r6, 16 - ssatx r12,r6, 16 - str r2, [r1, lr] @ fSZ(v) - cmp r3, r2, lsl #1 @ gteH < gteSZ3*2 ? - mov r9, #1<<30 - bhs 1f -.if 1 - udiv r9, r3, r2, r1, r4, r6, r7 -.else - push {r0, r12, lr} - mov r0, r3 - mov r1, r2 - bl DIVIDE - mov r9, r0 - pop {r0, r12, lr} -.endif -1: cmp r9, #0x20000 - add r1, r0, #4*12 - movhs r9, #0x20000 - ldrd r6, [r0,#4*(32+24)] @ gteOFXY - /* quotient */ subhs r9, #1 - mov r2, r6, asr #31 - smlal r6, r2, r10, r9 - mov r3, r7, asr #31 - smlal r7, r3, r11, r9 - lsr r6, #16 - orr r6, r2, lsl #16 @ (gteOFX + gteIR1 * q) >> 16 - ssatx_prep r2, 11 - lsr r7, #16 - orr r7, r3, lsl #16 @ (gteOFY + gteIR2 * q) >> 16 - ssatx r6, r2, 11 @ gteSX(v) - ssatx r7, r2, 11 @ gteSY(v) - strh r6, [r1, lr]! - add lr, #4 - strh r7, [r1, #2] - cmp lr, #12 - blt rtpt_arm_loop - - ldrd r4, [r0, #4*(32+27)] @ gteDQA, gteDQB - add r1, r0, #4*9 @ gteIR1 - mla r3, r4, r9, r5 @ gteDQB + gteDQA * q - stmia r1, {r10,r11,r12} @ gteIR123 save - - str r3, [r0,#4*24] @ gteMAC0 - asrs r3, #12 - movmi r3, #0 - cmp r3, #0x1000 @ limH - movgt r3, #0x1000 - str r3, [r0,#4*8] @ gteIR0 - - pop {r4-r11,pc} - .size gteRTPT_nf_arm, .-gteRTPT_nf_arm - - -@ note: not std calling convention used -@ r0 = CP2 (d,c) (must preserve) -@ r1 = needs_shift12 -@ r4,r5 = VXYZ(v) packed -@ r6 = &MX11(mx) -@ r7 = &CV1(cv) -.macro mvma_op do_flags - push {r8-r11} - -.if \do_flags - ands r3, r1, #1 @ gteFLAG, shift_need -.else - tst r1, #1 -.endif - ldmia r7, {r7-r9} @ CV123 - ldmia r6!,{r10-r12} @ MX1*,MX2* - asr r1, r7, #20 - lsl r7, #12 @ expand to 64bit - smlalbb r7, r1, r10, r4 @ MX11 * vx - smlaltt r7, r1, r10, r4 @ MX12 * vy - smlalbb r7, r1, r11, r5 @ MX13 * vz - lsrne r7, #12 - orrne r7, r1, lsl #20 @ gteMAC0 -.if \do_flags - asrne r1, #20 - adds r2, r7, #0x80000000 - adcs r1, #0 - orrgt r3, #(1<<30) - orrmi r3, #(1<<31)|(1<<27) - tst r3, #1 @ repeat shift test -.endif - asr r1, r8, #20 - lsl r8, #12 @ expand to 64bit - smlaltb r8, r1, r11, r4 @ MX21 * vx - smlalbt r8, r1, r12, r4 @ MX22 * vy - smlaltb r8, r1, r12, r5 @ MX23 * vz - lsrne r8, #12 - orrne r8, r1, lsl #20 @ gteMAC1 -.if \do_flags - asrne r1, #20 - adds r2, r8, #0x80000000 - adcs r1, #0 - orrgt r3, #(1<<29) - orrmi r3, #(1<<31)|(1<<26) - tst r3, #1 @ repeat shift test -.endif - ldmia r6!,{r10-r11} @ MX3* - asr r1, r9, #20 - lsl r9, #12 @ expand to 64bit - smlalbb r9, r1, r10, r4 @ MX31 * vx - smlaltt r9, r1, r10, r4 @ MX32 * vy - smlalbb r9, r1, r11, r5 @ MX33 * vz - lsrne r9, #12 - orrne r9, r1, lsl #20 @ gteMAC2 -.if \do_flags - asrne r1, #20 - adds r2, r9, #0x80000000 - adcs r1, #0 - orrgt r3, #(1<<28) - orrmi r3, #(1<<31)|(1<<25) - bic r3, #1 -.else - mov r3, #0 -.endif - str r3, [r0, #4*(32+31)] @ gteFLAG - add r1, r0, #4*25 - stmia r1, {r7-r9} - - pop {r8-r11} - bx lr -.endm - -.global gteMVMVA_part_arm -gteMVMVA_part_arm: - mvma_op 1 - .size gteMVMVA_part_arm, .-gteMVMVA_part_arm - -.global gteMVMVA_part_nf_arm -gteMVMVA_part_nf_arm: - mvma_op 0 - .size gteMVMVA_part_nf_arm, .-gteMVMVA_part_nf_arm - -@ common version of MVMVA with cv3 (== 0) and shift12, -@ can't overflow so no gteMAC flags needed -@ note: not std calling convention used -@ r0 = CP2 (d,c) (must preserve) -@ r4,r5 = VXYZ(v) packed -@ r6 = &MX11(mx) -.global gteMVMVA_part_cv3sh12_arm -gteMVMVA_part_cv3sh12_arm: - push {r8-r9} - ldmia r6!,{r7-r9} @ MX1*,MX2* - smulbb r1, r7, r4 @ MX11 * vx - smultt r2, r7, r4 @ MX12 * vy - smulbb r3, r8, r5 @ MX13 * vz - qadd r1, r1, r2 - asr r3, #1 @ prevent oflow, lose a bit - add r1, r3, r1, asr #1 - asr r7, r1, #11 - smultb r1, r8, r4 @ MX21 * vx - smulbt r2, r9, r4 @ MX22 * vy - smultb r3, r9, r5 @ MX23 * vz - qadd r1, r1, r2 - asr r3, #1 - add r1, r3, r1, asr #1 - asr r8, r1, #11 - ldmia r6, {r6,r9} @ MX3* - smulbb r1, r6, r4 @ MX31 * vx - smultt r2, r6, r4 @ MX32 * vy - smulbb r3, r9, r5 @ MX33 * vz - qadd r1, r1, r2 - asr r3, #1 - add r1, r3, r1, asr #1 - asr r9, r1, #11 - add r1, r0, #4*25 - mov r2, #0 - stmia r1, {r7-r9} - str r2, [r0, #4*(32+31)] @ gteFLAG - pop {r8-r9} - bx lr - .size gteMVMVA_part_cv3sh12_arm, .-gteMVMVA_part_cv3sh12_arm - - -.global gteNCLIP_arm @ r0=CP2 (d,c), -gteNCLIP_arm: - push {r4-r6,lr} - ldrsh r4, [r0, #4*12+2] - ldrsh r5, [r0, #4*13+2] - ldrsh r6, [r0, #4*14+2] - ldrsh lr, [r0, #4*12] - ldrsh r2, [r0, #4*13] - sub r12, r4, r5 @ 3: gteSY0 - gteSY1 - sub r5, r5, r6 @ 1: gteSY1 - gteSY2 - smull r1, r5, lr, r5 @ RdLo, RdHi - sub r6, r4 @ 2: gteSY2 - gteSY0 - ldrsh r3, [r0, #4*14] - smlal r1, r5, r2, r6 - mov lr, #0 @ gteFLAG - smlal r1, r5, r3, r12 - mov r6, #1<<31 - orr r6, #1<<15 - movs r2, r1, lsl #1 - adc r5, r5 - cmp r5, #0 -.if HAVE_ARMV7 - movtgt lr, #((1<<31)|(1<<16))>>16 -.else - movgt lr, #(1<<31) - orrgt lr, #(1<<16) -.endif - cmn r5, #1 - orrmi lr, r6 - str r1, [r0, #4*24] - str lr, [r0, #4*(32+31)] @ gteFLAG - - pop {r4-r6,pc} - .size gteNCLIP_arm, .-gteNCLIP_arm - - -.macro gteMACtoIR lm - ldr r2, [r0, #4*25] @ gteMAC1 - mov r1, #1<<15 - ldr r12,[r0, #4*(32+31)] @ gteFLAG - cmp r2, r1 - subge r2, r1, #1 - orrge r12, #(1<<31)|(1<<24) -.if \lm - cmp r2, #0 - movlt r2, #0 -.else - cmn r2, r1 - rsblt r2, r1, #0 -.endif - str r2, [r0, #4*9] - ldrd r2, [r0, #4*26] @ gteMAC23 - orrlt r12, #(1<<31)|(1<<24) - cmp r2, r1 - subge r2, r1, #1 - orrge r12, #1<<23 - orrge r12, #1<<31 -.if \lm - cmp r2, #0 - movlt r2, #0 -.else - cmn r2, r1 - rsblt r2, r1, #0 -.endif - orrlt r12, #1<<23 - orrlt r12, #1<<31 - cmp r3, r1 - subge r3, r1, #1 - orrge r12, #1<<22 -.if \lm - cmp r3, #0 - movlt r3, #0 -.else - cmn r3, r1 - rsblt r3, r1, #0 -.endif - orrlt r12, #1<<22 - strd r2, [r0, #4*10] @ gteIR23 - str r12,[r0, #4*(32+31)] @ gteFLAG - bx lr -.endm - -.global gteMACtoIR_lm0 @ r0=CP2 (d,c) -gteMACtoIR_lm0: - gteMACtoIR 0 - .size gteMACtoIR_lm0, .-gteMACtoIR_lm0 - -.global gteMACtoIR_lm1 @ r0=CP2 (d,c) -gteMACtoIR_lm1: - gteMACtoIR 1 - .size gteMACtoIR_lm1, .-gteMACtoIR_lm1 - - -.global gteMACtoIR_lm0_nf @ r0=CP2 (d,c) -gteMACtoIR_lm0_nf: - add r12, r0, #4*25 - ldmia r12, {r1-r3} - ssatx_prep r12, 16 - ssatx r1, r12, 16 - ssatx r2, r12, 16 - ssatx r3, r12, 16 - add r12, r0, #4*9 - stmia r12, {r1-r3} - bx lr - .size gteMACtoIR_lm0_nf, .-gteMACtoIR_lm0_nf - - -.global gteMACtoIR_lm1_nf @ r0=CP2 (d,c) -gteMACtoIR_lm1_nf: - add r12, r0, #4*25 - ldmia r12, {r1-r3} - ssatx0_prep r12, 16 - ssatx0 r1, r12, 16 - ssatx0 r2, r12, 16 - ssatx0 r3, r12, 16 - add r12, r0, #4*9 - stmia r12, {r1-r3} - bx lr - .size gteMACtoIR_lm1_nf, .-gteMACtoIR_lm1_nf - - -.if 0 -.global gteMVMVA_test -gteMVMVA_test: - push {r4-r7,lr} - push {r1} - and r2, r1, #0x18000 @ v - cmp r2, #0x18000 @ v == 3? - addeq r4, r0, #4*9 - addne r3, r0, r2, lsr #12 - ldmeqia r4, {r3-r5} - ldmneia r3, {r4,r5} - lsleq r3, #16 - lsreq r3, #16 - orreq r4, r3, r4, lsl #16 @ r4,r5 = VXYZ(v) - @and r5, #0xffff - add r12, r0, #4*32 - and r3, r1, #0x60000 @ mx - lsr r3, #17 - add r6, r12, r3, lsl #5 - cmp r3, #3 - adreq r6, zeroes - and r2, r1, #0x06000 @ cv - lsr r2, #13 - add r7, r12, r2, lsl #5 - add r7, #4*5 - cmp r2, #3 - adreq r7, zeroes -.if 1 - adr lr, 1f - bne 0f - tst r1, #1<<19 - bne gteMVMVA_part_cv3sh12_arm -0: - and r1, #1<<19 - lsr r1, #19 - b gteMVMVA_part_arm -1: - pop {r1} - tst r1, #1<<10 - adr lr, 0f - beq gteMACtoIR_lm0 - bne gteMACtoIR_lm1 -0: -.else - bl gteMVMVA_part_neon - pop {r1} - and r1, #1<<10 - bl gteMACtoIR_flags_neon -.endif - pop {r4-r7,pc} - -zeroes: - .word 0,0,0,0,0 -.endif - - -@ vim:filetype=armasm - -- cgit v1.2.3 From 159dc8eed41f86f841d7b0178ed6a015e8019a5e Mon Sep 17 00:00:00 2001 From: Toad King Date: Mon, 29 Oct 2012 13:26:25 -0400 Subject: rename gte_arm.S back to gte_arm.s, fixes compiling on non-Android platforms fix Android makefile to pass HAVE_ARMV7 symbol to assembler --- jni/Android.mk | 6 +- libpcsxcore/gte_arm.S | 590 -------------------------------------------------- libpcsxcore/gte_arm.s | 590 ++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 593 insertions(+), 593 deletions(-) delete mode 100644 libpcsxcore/gte_arm.S create mode 100644 libpcsxcore/gte_arm.s diff --git a/jni/Android.mk b/jni/Android.mk index 6be42b1..81b885d 100644 --- a/jni/Android.mk +++ b/jni/Android.mk @@ -20,14 +20,14 @@ ifeq ($(TARGET_ARCH),arm) LOCAL_ARM_MODE := arm ifeq ($(TARGET_ARCH_EABI),armeabi-v7a) - LOCAL_CFLAGS += -DHAVE_ARMV7=1 + LOCAL_CFLAGS += -Wa,--defsym,HAVE_ARMV7=1 else - LOCAL_CFLAGS += -DHAVE_ARMV7=0 + LOCAL_CFLAGS += -Wa,--defsym,HAVE_ARMV7=0 endif LOCAL_CFLAGS += -DANDROID_ARM - LOCAL_SRC_FILES += ../libpcsxcore/gte_arm.S + LOCAL_SRC_FILES += ../libpcsxcore/gte_arm.s # dynarec LOCAL_SRC_FILES += ../libpcsxcore/new_dynarec/new_dynarec.c ../libpcsxcore/new_dynarec/linkage_arm.S ../libpcsxcore/new_dynarec/emu_if.c ../libpcsxcore/new_dynarec/pcsxmem.c diff --git a/libpcsxcore/gte_arm.S b/libpcsxcore/gte_arm.S deleted file mode 100644 index 8700f69..0000000 --- a/libpcsxcore/gte_arm.S +++ /dev/null @@ -1,590 +0,0 @@ -/* - * (C) Gražvydas "notaz" Ignotas, 2011 - * - * This work is licensed under the terms of GNU GPL version 2 or later. - * See the COPYING file in the top-level directory. - */ - -/* .equiv HAVE_ARMV7, 1 */ - -.text -.align 2 - -.macro sgnxt16 rd rs -.if HAVE_ARMV7 - sxth \rd, \rs -.else - lsl \rd, \rs, #16 - asr \rd, \rd, #16 -.endif -.endm - -@ prepare work reg for ssatx -@ in: wr reg, bit to saturate to -.macro ssatx_prep wr bit -.if !HAVE_ARMV7 - mov \wr, #(1<<(\bit-1)) -.endif -.endm - -.macro ssatx rd wr bit -.if HAVE_ARMV7 - ssat \rd, #\bit, \rd -.else - cmp \rd, \wr - subge \rd, \wr, #1 - cmn \rd, \wr - rsblt \rd, \wr, #0 -.endif -.endm - -@ prepare work reg for ssatx0 (sat to 0..2^(bit-1)) -@ in: wr reg, bit to saturate to -.macro ssatx0_prep wr bit - mov \wr, #(1<<(\bit-1)) -.endm - -.macro ssatx0 rd wr bit - cmp \rd, \wr - subge \rd, \wr, #1 - cmn \rd, #0 - movlt \rd, #0 -.endm - -.macro usat16_ rd rs -.if HAVE_ARMV7 - usat \rd, #16, \rs -.else - subs \rd, \rs, #0 - movlt \rd, #0 - cmp \rd, #0x10000 - movge \rd, #0x0ff00 - orrge \rd, #0x000ff -.endif -.endm - -.macro udiv_ rd rm rs - lsl \rm, #16 - clz \rd, \rs - lsl \rs, \rs, \rd @ shift up divisor - orr \rd, \rd, #1<<31 - lsr \rd, \rd, \rd -0: - cmp \rm, \rs - subcs \rm, \rs - adcs \rd, \rd, \rd - lsr \rs, #1 - bcc 0b -.endm - -.macro newton_step rcp den zero t1 t2 - umull \t2, \t1, \den, \rcp @ \t2 is dummy - sub \t1, \zero, \t1, lsl #2 - smlal \t2, \rcp, \t1, \rcp -.endm - -.macro udiv_newton rd rm rs t1 t2 t3 t4 - lsl \rd, \rm, #16 - clz \t1, \rs - mov \t2, #0 - lsl \rs, \t1 @ normalize for the algo - mov \rm, #0x4d000000 @ initial estimate ~1.2 - - newton_step \rm, \rs, \t2, \t3, \t4 - newton_step \rm, \rs, \t2, \t3, \t4 - newton_step \rm, \rs, \t2, \t3, \t4 - newton_step \rm, \rs, \t2, \t3, \t4 - - umull \t4, \rd, \rm, \rd - rsb \t2, \t1, #30 @ here t1 is 1..15 - mov \rd, \rd, lsr \t2 -.endm - -@ unsigned divide rd = rm / rs; 16.16 result -@ no div by 0 check -@ in: rm, rs -@ trash: rm rs t* -.macro udiv rd rm rs t1 t2 t3 t4 - @udiv_ \rd, \rm, \rs - udiv_newton \rd, \rm, \rs, \t1, \t2, \t3, \t4 -.endm - -@ calculate RTPS/RTPT MAC values -@ in: r0 context, r8,r9 VXYZ -@ out: r10-r12 MAC123 -@ trash: r1-r7 -.macro do_rtpx_mac - add r1, r0, #4*32 - add r2, r0, #4*(32+5) @ gteTRX - ldmia r1!,{r5-r7} @ gteR1*,gteR2* - ldmia r2, {r10-r12} - smulbb r2, r5, r8 @ gteR11 * gteVX0 - smultt r3, r5, r8 @ gteR12 * gteVY0 - smulbb r4, r6, r9 @ gteR13 * gteVZ0 - qadd r2, r2, r3 - asr r4, r4, #1 @ prevent oflow, lose a bit - add r3, r4, r2, asr #1 - add r10,r10,r3, asr #11 @ gteMAC1 - smultb r2, r6, r8 @ gteR21 * gteVX0 - smulbt r3, r7, r8 @ gteR22 * gteVY0 - smultb r4, r7, r9 @ gteR23 * gteVZ0 - ldmia r1!,{r5-r6} @ gteR3* - qadd r2, r2, r3 - asr r4, r4, #1 - add r3, r4, r2, asr #1 - add r11,r11,r3, asr #11 @ gteMAC2 - @ be more accurate for gteMAC3, since it's also a divider - smulbb r2, r5, r8 @ gteR31 * gteVX0 - smultt r3, r5, r8 @ gteR32 * gteVY0 - smulbb r4, r6, r9 @ gteR33 * gteVZ0 - qadd r2, r2, r3 - asr r3, r4, #31 @ expand to 64bit - adds r1, r2, r4 - adc r3, r2, asr #31 @ 64bit sum in r3,r1 - add r12,r12,r3, lsl #20 - add r12,r12,r1, lsr #12 @ gteMAC3 -.endm - - -.global gteRTPS_nf_arm @ r0=CP2 (d,c), -gteRTPS_nf_arm: - push {r4-r11,lr} - - ldmia r0, {r8,r9} @ VXYZ(0) - do_rtpx_mac - add r1, r0, #4*25 @ gteMAC1 - add r2, r0, #4*17 @ gteSZ1 - stmia r1, {r10-r12} @ gteMAC123 save - ldmia r2, {r3-r5} - add r1, r0, #4*16 @ gteSZ0 - add r2, r0, #4*9 @ gteIR1 - ssatx_prep r6, 16 - usat16_ lr, r12 @ limD - ssatx r10,r6, 16 - ssatx r11,r6, 16 - ssatx r12,r6, 16 - stmia r1, {r3-r5,lr} @ gteSZ* - ldr r3, [r0,#4*(32+26)] @ gteH - stmia r2, {r10,r11,r12} @ gteIR123 save - cmp r3, lr, lsl #1 @ gteH < gteSZ3*2 ? - mov r9, #1<<30 - bhs 1f -.if 1 - udiv r9, r3, lr, r1, r2, r6, r7 -.else - push {r0, r12} - mov r0, r3 - mov r1, lr - bl DIVIDE - mov r9, r0 - pop {r0, r12} -.endif -1: - ldrd r6, [r0,#4*(32+24)] @ gteOFXY - cmp r9, #0x20000 - add r1, r0, #4*12 @ gteSXY0 - movhs r9, #0x20000 - ldmia r1, {r2-r4} - /* quotient */ subhs r9, #1 - mov r2, r6, asr #31 - smlal r6, r2, r10, r9 - stmia r1!,{r3,r4} @ shift gteSXY - mov r3, r7, asr #31 - smlal r7, r3, r11, r9 - lsr r6, #16 - /* gteDQA, gteDQB */ ldrd r10,[r0, #4*(32+27)] - orr r6, r2, lsl #16 @ (gteOFX + gteIR1 * q) >> 16 - ssatx_prep r2, 11 - lsr r7, #16 - /* gteDQB + gteDQA * q */ mla r4, r10, r9, r11 - orr r7, r3, lsl #16 @ (gteOFY + gteIR2 * q) >> 16 - ssatx r6, r2, 11 @ gteSX2 - ssatx r7, r2, 11 @ gteSY2 - strh r6, [r1] - strh r7, [r1, #2] - str r4, [r0,#4*24] @ gteMAC0 - asrs r4, #12 - movmi r4, #0 - cmp r4, #0x1000 @ limH - movgt r4, #0x1000 - str r4, [r0,#4*8] @ gteIR0 - - pop {r4-r11,pc} - .size gteRTPS_nf_arm, .-gteRTPS_nf_arm - - -.global gteRTPT_nf_arm @ r0=CP2 (d,c), -gteRTPT_nf_arm: - ldr r1, [r0, #4*19] @ gteSZ3 - push {r4-r11,lr} - str r1, [r0, #4*16] @ gteSZ0 - mov lr, #0 - -rtpt_arm_loop: - add r1, r0, lr, lsl #1 - ldrd r8, [r1] @ VXYZ(v) - do_rtpx_mac - - ssatx_prep r6, 16 - usat16_ r2, r12 @ limD - add r1, r0, #4*25 @ gteMAC1 - ldr r3, [r0,#4*(32+26)] @ gteH - stmia r1, {r10-r12} @ gteMAC123 save - add r1, r0, #4*17 - ssatx r10,r6, 16 - ssatx r11,r6, 16 - ssatx r12,r6, 16 - str r2, [r1, lr] @ fSZ(v) - cmp r3, r2, lsl #1 @ gteH < gteSZ3*2 ? - mov r9, #1<<30 - bhs 1f -.if 1 - udiv r9, r3, r2, r1, r4, r6, r7 -.else - push {r0, r12, lr} - mov r0, r3 - mov r1, r2 - bl DIVIDE - mov r9, r0 - pop {r0, r12, lr} -.endif -1: cmp r9, #0x20000 - add r1, r0, #4*12 - movhs r9, #0x20000 - ldrd r6, [r0,#4*(32+24)] @ gteOFXY - /* quotient */ subhs r9, #1 - mov r2, r6, asr #31 - smlal r6, r2, r10, r9 - mov r3, r7, asr #31 - smlal r7, r3, r11, r9 - lsr r6, #16 - orr r6, r2, lsl #16 @ (gteOFX + gteIR1 * q) >> 16 - ssatx_prep r2, 11 - lsr r7, #16 - orr r7, r3, lsl #16 @ (gteOFY + gteIR2 * q) >> 16 - ssatx r6, r2, 11 @ gteSX(v) - ssatx r7, r2, 11 @ gteSY(v) - strh r6, [r1, lr]! - add lr, #4 - strh r7, [r1, #2] - cmp lr, #12 - blt rtpt_arm_loop - - ldrd r4, [r0, #4*(32+27)] @ gteDQA, gteDQB - add r1, r0, #4*9 @ gteIR1 - mla r3, r4, r9, r5 @ gteDQB + gteDQA * q - stmia r1, {r10,r11,r12} @ gteIR123 save - - str r3, [r0,#4*24] @ gteMAC0 - asrs r3, #12 - movmi r3, #0 - cmp r3, #0x1000 @ limH - movgt r3, #0x1000 - str r3, [r0,#4*8] @ gteIR0 - - pop {r4-r11,pc} - .size gteRTPT_nf_arm, .-gteRTPT_nf_arm - - -@ note: not std calling convention used -@ r0 = CP2 (d,c) (must preserve) -@ r1 = needs_shift12 -@ r4,r5 = VXYZ(v) packed -@ r6 = &MX11(mx) -@ r7 = &CV1(cv) -.macro mvma_op do_flags - push {r8-r11} - -.if \do_flags - ands r3, r1, #1 @ gteFLAG, shift_need -.else - tst r1, #1 -.endif - ldmia r7, {r7-r9} @ CV123 - ldmia r6!,{r10-r12} @ MX1*,MX2* - asr r1, r7, #20 - lsl r7, #12 @ expand to 64bit - smlalbb r7, r1, r10, r4 @ MX11 * vx - smlaltt r7, r1, r10, r4 @ MX12 * vy - smlalbb r7, r1, r11, r5 @ MX13 * vz - lsrne r7, #12 - orrne r7, r1, lsl #20 @ gteMAC0 -.if \do_flags - asrne r1, #20 - adds r2, r7, #0x80000000 - adcs r1, #0 - orrgt r3, #(1<<30) - orrmi r3, #(1<<31)|(1<<27) - tst r3, #1 @ repeat shift test -.endif - asr r1, r8, #20 - lsl r8, #12 @ expand to 64bit - smlaltb r8, r1, r11, r4 @ MX21 * vx - smlalbt r8, r1, r12, r4 @ MX22 * vy - smlaltb r8, r1, r12, r5 @ MX23 * vz - lsrne r8, #12 - orrne r8, r1, lsl #20 @ gteMAC1 -.if \do_flags - asrne r1, #20 - adds r2, r8, #0x80000000 - adcs r1, #0 - orrgt r3, #(1<<29) - orrmi r3, #(1<<31)|(1<<26) - tst r3, #1 @ repeat shift test -.endif - ldmia r6!,{r10-r11} @ MX3* - asr r1, r9, #20 - lsl r9, #12 @ expand to 64bit - smlalbb r9, r1, r10, r4 @ MX31 * vx - smlaltt r9, r1, r10, r4 @ MX32 * vy - smlalbb r9, r1, r11, r5 @ MX33 * vz - lsrne r9, #12 - orrne r9, r1, lsl #20 @ gteMAC2 -.if \do_flags - asrne r1, #20 - adds r2, r9, #0x80000000 - adcs r1, #0 - orrgt r3, #(1<<28) - orrmi r3, #(1<<31)|(1<<25) - bic r3, #1 -.else - mov r3, #0 -.endif - str r3, [r0, #4*(32+31)] @ gteFLAG - add r1, r0, #4*25 - stmia r1, {r7-r9} - - pop {r8-r11} - bx lr -.endm - -.global gteMVMVA_part_arm -gteMVMVA_part_arm: - mvma_op 1 - .size gteMVMVA_part_arm, .-gteMVMVA_part_arm - -.global gteMVMVA_part_nf_arm -gteMVMVA_part_nf_arm: - mvma_op 0 - .size gteMVMVA_part_nf_arm, .-gteMVMVA_part_nf_arm - -@ common version of MVMVA with cv3 (== 0) and shift12, -@ can't overflow so no gteMAC flags needed -@ note: not std calling convention used -@ r0 = CP2 (d,c) (must preserve) -@ r4,r5 = VXYZ(v) packed -@ r6 = &MX11(mx) -.global gteMVMVA_part_cv3sh12_arm -gteMVMVA_part_cv3sh12_arm: - push {r8-r9} - ldmia r6!,{r7-r9} @ MX1*,MX2* - smulbb r1, r7, r4 @ MX11 * vx - smultt r2, r7, r4 @ MX12 * vy - smulbb r3, r8, r5 @ MX13 * vz - qadd r1, r1, r2 - asr r3, #1 @ prevent oflow, lose a bit - add r1, r3, r1, asr #1 - asr r7, r1, #11 - smultb r1, r8, r4 @ MX21 * vx - smulbt r2, r9, r4 @ MX22 * vy - smultb r3, r9, r5 @ MX23 * vz - qadd r1, r1, r2 - asr r3, #1 - add r1, r3, r1, asr #1 - asr r8, r1, #11 - ldmia r6, {r6,r9} @ MX3* - smulbb r1, r6, r4 @ MX31 * vx - smultt r2, r6, r4 @ MX32 * vy - smulbb r3, r9, r5 @ MX33 * vz - qadd r1, r1, r2 - asr r3, #1 - add r1, r3, r1, asr #1 - asr r9, r1, #11 - add r1, r0, #4*25 - mov r2, #0 - stmia r1, {r7-r9} - str r2, [r0, #4*(32+31)] @ gteFLAG - pop {r8-r9} - bx lr - .size gteMVMVA_part_cv3sh12_arm, .-gteMVMVA_part_cv3sh12_arm - - -.global gteNCLIP_arm @ r0=CP2 (d,c), -gteNCLIP_arm: - push {r4-r6,lr} - ldrsh r4, [r0, #4*12+2] - ldrsh r5, [r0, #4*13+2] - ldrsh r6, [r0, #4*14+2] - ldrsh lr, [r0, #4*12] - ldrsh r2, [r0, #4*13] - sub r12, r4, r5 @ 3: gteSY0 - gteSY1 - sub r5, r5, r6 @ 1: gteSY1 - gteSY2 - smull r1, r5, lr, r5 @ RdLo, RdHi - sub r6, r4 @ 2: gteSY2 - gteSY0 - ldrsh r3, [r0, #4*14] - smlal r1, r5, r2, r6 - mov lr, #0 @ gteFLAG - smlal r1, r5, r3, r12 - mov r6, #1<<31 - orr r6, #1<<15 - movs r2, r1, lsl #1 - adc r5, r5 - cmp r5, #0 -.if HAVE_ARMV7 - movtgt lr, #((1<<31)|(1<<16))>>16 -.else - movgt lr, #(1<<31) - orrgt lr, #(1<<16) -.endif - cmn r5, #1 - orrmi lr, r6 - str r1, [r0, #4*24] - str lr, [r0, #4*(32+31)] @ gteFLAG - - pop {r4-r6,pc} - .size gteNCLIP_arm, .-gteNCLIP_arm - - -.macro gteMACtoIR lm - ldr r2, [r0, #4*25] @ gteMAC1 - mov r1, #1<<15 - ldr r12,[r0, #4*(32+31)] @ gteFLAG - cmp r2, r1 - subge r2, r1, #1 - orrge r12, #(1<<31)|(1<<24) -.if \lm - cmp r2, #0 - movlt r2, #0 -.else - cmn r2, r1 - rsblt r2, r1, #0 -.endif - str r2, [r0, #4*9] - ldrd r2, [r0, #4*26] @ gteMAC23 - orrlt r12, #(1<<31)|(1<<24) - cmp r2, r1 - subge r2, r1, #1 - orrge r12, #1<<23 - orrge r12, #1<<31 -.if \lm - cmp r2, #0 - movlt r2, #0 -.else - cmn r2, r1 - rsblt r2, r1, #0 -.endif - orrlt r12, #1<<23 - orrlt r12, #1<<31 - cmp r3, r1 - subge r3, r1, #1 - orrge r12, #1<<22 -.if \lm - cmp r3, #0 - movlt r3, #0 -.else - cmn r3, r1 - rsblt r3, r1, #0 -.endif - orrlt r12, #1<<22 - strd r2, [r0, #4*10] @ gteIR23 - str r12,[r0, #4*(32+31)] @ gteFLAG - bx lr -.endm - -.global gteMACtoIR_lm0 @ r0=CP2 (d,c) -gteMACtoIR_lm0: - gteMACtoIR 0 - .size gteMACtoIR_lm0, .-gteMACtoIR_lm0 - -.global gteMACtoIR_lm1 @ r0=CP2 (d,c) -gteMACtoIR_lm1: - gteMACtoIR 1 - .size gteMACtoIR_lm1, .-gteMACtoIR_lm1 - - -.global gteMACtoIR_lm0_nf @ r0=CP2 (d,c) -gteMACtoIR_lm0_nf: - add r12, r0, #4*25 - ldmia r12, {r1-r3} - ssatx_prep r12, 16 - ssatx r1, r12, 16 - ssatx r2, r12, 16 - ssatx r3, r12, 16 - add r12, r0, #4*9 - stmia r12, {r1-r3} - bx lr - .size gteMACtoIR_lm0_nf, .-gteMACtoIR_lm0_nf - - -.global gteMACtoIR_lm1_nf @ r0=CP2 (d,c) -gteMACtoIR_lm1_nf: - add r12, r0, #4*25 - ldmia r12, {r1-r3} - ssatx0_prep r12, 16 - ssatx0 r1, r12, 16 - ssatx0 r2, r12, 16 - ssatx0 r3, r12, 16 - add r12, r0, #4*9 - stmia r12, {r1-r3} - bx lr - .size gteMACtoIR_lm1_nf, .-gteMACtoIR_lm1_nf - - -.if 0 -.global gteMVMVA_test -gteMVMVA_test: - push {r4-r7,lr} - push {r1} - and r2, r1, #0x18000 @ v - cmp r2, #0x18000 @ v == 3? - addeq r4, r0, #4*9 - addne r3, r0, r2, lsr #12 - ldmeqia r4, {r3-r5} - ldmneia r3, {r4,r5} - lsleq r3, #16 - lsreq r3, #16 - orreq r4, r3, r4, lsl #16 @ r4,r5 = VXYZ(v) - @and r5, #0xffff - add r12, r0, #4*32 - and r3, r1, #0x60000 @ mx - lsr r3, #17 - add r6, r12, r3, lsl #5 - cmp r3, #3 - adreq r6, zeroes - and r2, r1, #0x06000 @ cv - lsr r2, #13 - add r7, r12, r2, lsl #5 - add r7, #4*5 - cmp r2, #3 - adreq r7, zeroes -.if 1 - adr lr, 1f - bne 0f - tst r1, #1<<19 - bne gteMVMVA_part_cv3sh12_arm -0: - and r1, #1<<19 - lsr r1, #19 - b gteMVMVA_part_arm -1: - pop {r1} - tst r1, #1<<10 - adr lr, 0f - beq gteMACtoIR_lm0 - bne gteMACtoIR_lm1 -0: -.else - bl gteMVMVA_part_neon - pop {r1} - and r1, #1<<10 - bl gteMACtoIR_flags_neon -.endif - pop {r4-r7,pc} - -zeroes: - .word 0,0,0,0,0 -.endif - - -@ vim:filetype=armasm - diff --git a/libpcsxcore/gte_arm.s b/libpcsxcore/gte_arm.s new file mode 100644 index 0000000..8700f69 --- /dev/null +++ b/libpcsxcore/gte_arm.s @@ -0,0 +1,590 @@ +/* + * (C) Gražvydas "notaz" Ignotas, 2011 + * + * This work is licensed under the terms of GNU GPL version 2 or later. + * See the COPYING file in the top-level directory. + */ + +/* .equiv HAVE_ARMV7, 1 */ + +.text +.align 2 + +.macro sgnxt16 rd rs +.if HAVE_ARMV7 + sxth \rd, \rs +.else + lsl \rd, \rs, #16 + asr \rd, \rd, #16 +.endif +.endm + +@ prepare work reg for ssatx +@ in: wr reg, bit to saturate to +.macro ssatx_prep wr bit +.if !HAVE_ARMV7 + mov \wr, #(1<<(\bit-1)) +.endif +.endm + +.macro ssatx rd wr bit +.if HAVE_ARMV7 + ssat \rd, #\bit, \rd +.else + cmp \rd, \wr + subge \rd, \wr, #1 + cmn \rd, \wr + rsblt \rd, \wr, #0 +.endif +.endm + +@ prepare work reg for ssatx0 (sat to 0..2^(bit-1)) +@ in: wr reg, bit to saturate to +.macro ssatx0_prep wr bit + mov \wr, #(1<<(\bit-1)) +.endm + +.macro ssatx0 rd wr bit + cmp \rd, \wr + subge \rd, \wr, #1 + cmn \rd, #0 + movlt \rd, #0 +.endm + +.macro usat16_ rd rs +.if HAVE_ARMV7 + usat \rd, #16, \rs +.else + subs \rd, \rs, #0 + movlt \rd, #0 + cmp \rd, #0x10000 + movge \rd, #0x0ff00 + orrge \rd, #0x000ff +.endif +.endm + +.macro udiv_ rd rm rs + lsl \rm, #16 + clz \rd, \rs + lsl \rs, \rs, \rd @ shift up divisor + orr \rd, \rd, #1<<31 + lsr \rd, \rd, \rd +0: + cmp \rm, \rs + subcs \rm, \rs + adcs \rd, \rd, \rd + lsr \rs, #1 + bcc 0b +.endm + +.macro newton_step rcp den zero t1 t2 + umull \t2, \t1, \den, \rcp @ \t2 is dummy + sub \t1, \zero, \t1, lsl #2 + smlal \t2, \rcp, \t1, \rcp +.endm + +.macro udiv_newton rd rm rs t1 t2 t3 t4 + lsl \rd, \rm, #16 + clz \t1, \rs + mov \t2, #0 + lsl \rs, \t1 @ normalize for the algo + mov \rm, #0x4d000000 @ initial estimate ~1.2 + + newton_step \rm, \rs, \t2, \t3, \t4 + newton_step \rm, \rs, \t2, \t3, \t4 + newton_step \rm, \rs, \t2, \t3, \t4 + newton_step \rm, \rs, \t2, \t3, \t4 + + umull \t4, \rd, \rm, \rd + rsb \t2, \t1, #30 @ here t1 is 1..15 + mov \rd, \rd, lsr \t2 +.endm + +@ unsigned divide rd = rm / rs; 16.16 result +@ no div by 0 check +@ in: rm, rs +@ trash: rm rs t* +.macro udiv rd rm rs t1 t2 t3 t4 + @udiv_ \rd, \rm, \rs + udiv_newton \rd, \rm, \rs, \t1, \t2, \t3, \t4 +.endm + +@ calculate RTPS/RTPT MAC values +@ in: r0 context, r8,r9 VXYZ +@ out: r10-r12 MAC123 +@ trash: r1-r7 +.macro do_rtpx_mac + add r1, r0, #4*32 + add r2, r0, #4*(32+5) @ gteTRX + ldmia r1!,{r5-r7} @ gteR1*,gteR2* + ldmia r2, {r10-r12} + smulbb r2, r5, r8 @ gteR11 * gteVX0 + smultt r3, r5, r8 @ gteR12 * gteVY0 + smulbb r4, r6, r9 @ gteR13 * gteVZ0 + qadd r2, r2, r3 + asr r4, r4, #1 @ prevent oflow, lose a bit + add r3, r4, r2, asr #1 + add r10,r10,r3, asr #11 @ gteMAC1 + smultb r2, r6, r8 @ gteR21 * gteVX0 + smulbt r3, r7, r8 @ gteR22 * gteVY0 + smultb r4, r7, r9 @ gteR23 * gteVZ0 + ldmia r1!,{r5-r6} @ gteR3* + qadd r2, r2, r3 + asr r4, r4, #1 + add r3, r4, r2, asr #1 + add r11,r11,r3, asr #11 @ gteMAC2 + @ be more accurate for gteMAC3, since it's also a divider + smulbb r2, r5, r8 @ gteR31 * gteVX0 + smultt r3, r5, r8 @ gteR32 * gteVY0 + smulbb r4, r6, r9 @ gteR33 * gteVZ0 + qadd r2, r2, r3 + asr r3, r4, #31 @ expand to 64bit + adds r1, r2, r4 + adc r3, r2, asr #31 @ 64bit sum in r3,r1 + add r12,r12,r3, lsl #20 + add r12,r12,r1, lsr #12 @ gteMAC3 +.endm + + +.global gteRTPS_nf_arm @ r0=CP2 (d,c), +gteRTPS_nf_arm: + push {r4-r11,lr} + + ldmia r0, {r8,r9} @ VXYZ(0) + do_rtpx_mac + add r1, r0, #4*25 @ gteMAC1 + add r2, r0, #4*17 @ gteSZ1 + stmia r1, {r10-r12} @ gteMAC123 save + ldmia r2, {r3-r5} + add r1, r0, #4*16 @ gteSZ0 + add r2, r0, #4*9 @ gteIR1 + ssatx_prep r6, 16 + usat16_ lr, r12 @ limD + ssatx r10,r6, 16 + ssatx r11,r6, 16 + ssatx r12,r6, 16 + stmia r1, {r3-r5,lr} @ gteSZ* + ldr r3, [r0,#4*(32+26)] @ gteH + stmia r2, {r10,r11,r12} @ gteIR123 save + cmp r3, lr, lsl #1 @ gteH < gteSZ3*2 ? + mov r9, #1<<30 + bhs 1f +.if 1 + udiv r9, r3, lr, r1, r2, r6, r7 +.else + push {r0, r12} + mov r0, r3 + mov r1, lr + bl DIVIDE + mov r9, r0 + pop {r0, r12} +.endif +1: + ldrd r6, [r0,#4*(32+24)] @ gteOFXY + cmp r9, #0x20000 + add r1, r0, #4*12 @ gteSXY0 + movhs r9, #0x20000 + ldmia r1, {r2-r4} + /* quotient */ subhs r9, #1 + mov r2, r6, asr #31 + smlal r6, r2, r10, r9 + stmia r1!,{r3,r4} @ shift gteSXY + mov r3, r7, asr #31 + smlal r7, r3, r11, r9 + lsr r6, #16 + /* gteDQA, gteDQB */ ldrd r10,[r0, #4*(32+27)] + orr r6, r2, lsl #16 @ (gteOFX + gteIR1 * q) >> 16 + ssatx_prep r2, 11 + lsr r7, #16 + /* gteDQB + gteDQA * q */ mla r4, r10, r9, r11 + orr r7, r3, lsl #16 @ (gteOFY + gteIR2 * q) >> 16 + ssatx r6, r2, 11 @ gteSX2 + ssatx r7, r2, 11 @ gteSY2 + strh r6, [r1] + strh r7, [r1, #2] + str r4, [r0,#4*24] @ gteMAC0 + asrs r4, #12 + movmi r4, #0 + cmp r4, #0x1000 @ limH + movgt r4, #0x1000 + str r4, [r0,#4*8] @ gteIR0 + + pop {r4-r11,pc} + .size gteRTPS_nf_arm, .-gteRTPS_nf_arm + + +.global gteRTPT_nf_arm @ r0=CP2 (d,c), +gteRTPT_nf_arm: + ldr r1, [r0, #4*19] @ gteSZ3 + push {r4-r11,lr} + str r1, [r0, #4*16] @ gteSZ0 + mov lr, #0 + +rtpt_arm_loop: + add r1, r0, lr, lsl #1 + ldrd r8, [r1] @ VXYZ(v) + do_rtpx_mac + + ssatx_prep r6, 16 + usat16_ r2, r12 @ limD + add r1, r0, #4*25 @ gteMAC1 + ldr r3, [r0,#4*(32+26)] @ gteH + stmia r1, {r10-r12} @ gteMAC123 save + add r1, r0, #4*17 + ssatx r10,r6, 16 + ssatx r11,r6, 16 + ssatx r12,r6, 16 + str r2, [r1, lr] @ fSZ(v) + cmp r3, r2, lsl #1 @ gteH < gteSZ3*2 ? + mov r9, #1<<30 + bhs 1f +.if 1 + udiv r9, r3, r2, r1, r4, r6, r7 +.else + push {r0, r12, lr} + mov r0, r3 + mov r1, r2 + bl DIVIDE + mov r9, r0 + pop {r0, r12, lr} +.endif +1: cmp r9, #0x20000 + add r1, r0, #4*12 + movhs r9, #0x20000 + ldrd r6, [r0,#4*(32+24)] @ gteOFXY + /* quotient */ subhs r9, #1 + mov r2, r6, asr #31 + smlal r6, r2, r10, r9 + mov r3, r7, asr #31 + smlal r7, r3, r11, r9 + lsr r6, #16 + orr r6, r2, lsl #16 @ (gteOFX + gteIR1 * q) >> 16 + ssatx_prep r2, 11 + lsr r7, #16 + orr r7, r3, lsl #16 @ (gteOFY + gteIR2 * q) >> 16 + ssatx r6, r2, 11 @ gteSX(v) + ssatx r7, r2, 11 @ gteSY(v) + strh r6, [r1, lr]! + add lr, #4 + strh r7, [r1, #2] + cmp lr, #12 + blt rtpt_arm_loop + + ldrd r4, [r0, #4*(32+27)] @ gteDQA, gteDQB + add r1, r0, #4*9 @ gteIR1 + mla r3, r4, r9, r5 @ gteDQB + gteDQA * q + stmia r1, {r10,r11,r12} @ gteIR123 save + + str r3, [r0,#4*24] @ gteMAC0 + asrs r3, #12 + movmi r3, #0 + cmp r3, #0x1000 @ limH + movgt r3, #0x1000 + str r3, [r0,#4*8] @ gteIR0 + + pop {r4-r11,pc} + .size gteRTPT_nf_arm, .-gteRTPT_nf_arm + + +@ note: not std calling convention used +@ r0 = CP2 (d,c) (must preserve) +@ r1 = needs_shift12 +@ r4,r5 = VXYZ(v) packed +@ r6 = &MX11(mx) +@ r7 = &CV1(cv) +.macro mvma_op do_flags + push {r8-r11} + +.if \do_flags + ands r3, r1, #1 @ gteFLAG, shift_need +.else + tst r1, #1 +.endif + ldmia r7, {r7-r9} @ CV123 + ldmia r6!,{r10-r12} @ MX1*,MX2* + asr r1, r7, #20 + lsl r7, #12 @ expand to 64bit + smlalbb r7, r1, r10, r4 @ MX11 * vx + smlaltt r7, r1, r10, r4 @ MX12 * vy + smlalbb r7, r1, r11, r5 @ MX13 * vz + lsrne r7, #12 + orrne r7, r1, lsl #20 @ gteMAC0 +.if \do_flags + asrne r1, #20 + adds r2, r7, #0x80000000 + adcs r1, #0 + orrgt r3, #(1<<30) + orrmi r3, #(1<<31)|(1<<27) + tst r3, #1 @ repeat shift test +.endif + asr r1, r8, #20 + lsl r8, #12 @ expand to 64bit + smlaltb r8, r1, r11, r4 @ MX21 * vx + smlalbt r8, r1, r12, r4 @ MX22 * vy + smlaltb r8, r1, r12, r5 @ MX23 * vz + lsrne r8, #12 + orrne r8, r1, lsl #20 @ gteMAC1 +.if \do_flags + asrne r1, #20 + adds r2, r8, #0x80000000 + adcs r1, #0 + orrgt r3, #(1<<29) + orrmi r3, #(1<<31)|(1<<26) + tst r3, #1 @ repeat shift test +.endif + ldmia r6!,{r10-r11} @ MX3* + asr r1, r9, #20 + lsl r9, #12 @ expand to 64bit + smlalbb r9, r1, r10, r4 @ MX31 * vx + smlaltt r9, r1, r10, r4 @ MX32 * vy + smlalbb r9, r1, r11, r5 @ MX33 * vz + lsrne r9, #12 + orrne r9, r1, lsl #20 @ gteMAC2 +.if \do_flags + asrne r1, #20 + adds r2, r9, #0x80000000 + adcs r1, #0 + orrgt r3, #(1<<28) + orrmi r3, #(1<<31)|(1<<25) + bic r3, #1 +.else + mov r3, #0 +.endif + str r3, [r0, #4*(32+31)] @ gteFLAG + add r1, r0, #4*25 + stmia r1, {r7-r9} + + pop {r8-r11} + bx lr +.endm + +.global gteMVMVA_part_arm +gteMVMVA_part_arm: + mvma_op 1 + .size gteMVMVA_part_arm, .-gteMVMVA_part_arm + +.global gteMVMVA_part_nf_arm +gteMVMVA_part_nf_arm: + mvma_op 0 + .size gteMVMVA_part_nf_arm, .-gteMVMVA_part_nf_arm + +@ common version of MVMVA with cv3 (== 0) and shift12, +@ can't overflow so no gteMAC flags needed +@ note: not std calling convention used +@ r0 = CP2 (d,c) (must preserve) +@ r4,r5 = VXYZ(v) packed +@ r6 = &MX11(mx) +.global gteMVMVA_part_cv3sh12_arm +gteMVMVA_part_cv3sh12_arm: + push {r8-r9} + ldmia r6!,{r7-r9} @ MX1*,MX2* + smulbb r1, r7, r4 @ MX11 * vx + smultt r2, r7, r4 @ MX12 * vy + smulbb r3, r8, r5 @ MX13 * vz + qadd r1, r1, r2 + asr r3, #1 @ prevent oflow, lose a bit + add r1, r3, r1, asr #1 + asr r7, r1, #11 + smultb r1, r8, r4 @ MX21 * vx + smulbt r2, r9, r4 @ MX22 * vy + smultb r3, r9, r5 @ MX23 * vz + qadd r1, r1, r2 + asr r3, #1 + add r1, r3, r1, asr #1 + asr r8, r1, #11 + ldmia r6, {r6,r9} @ MX3* + smulbb r1, r6, r4 @ MX31 * vx + smultt r2, r6, r4 @ MX32 * vy + smulbb r3, r9, r5 @ MX33 * vz + qadd r1, r1, r2 + asr r3, #1 + add r1, r3, r1, asr #1 + asr r9, r1, #11 + add r1, r0, #4*25 + mov r2, #0 + stmia r1, {r7-r9} + str r2, [r0, #4*(32+31)] @ gteFLAG + pop {r8-r9} + bx lr + .size gteMVMVA_part_cv3sh12_arm, .-gteMVMVA_part_cv3sh12_arm + + +.global gteNCLIP_arm @ r0=CP2 (d,c), +gteNCLIP_arm: + push {r4-r6,lr} + ldrsh r4, [r0, #4*12+2] + ldrsh r5, [r0, #4*13+2] + ldrsh r6, [r0, #4*14+2] + ldrsh lr, [r0, #4*12] + ldrsh r2, [r0, #4*13] + sub r12, r4, r5 @ 3: gteSY0 - gteSY1 + sub r5, r5, r6 @ 1: gteSY1 - gteSY2 + smull r1, r5, lr, r5 @ RdLo, RdHi + sub r6, r4 @ 2: gteSY2 - gteSY0 + ldrsh r3, [r0, #4*14] + smlal r1, r5, r2, r6 + mov lr, #0 @ gteFLAG + smlal r1, r5, r3, r12 + mov r6, #1<<31 + orr r6, #1<<15 + movs r2, r1, lsl #1 + adc r5, r5 + cmp r5, #0 +.if HAVE_ARMV7 + movtgt lr, #((1<<31)|(1<<16))>>16 +.else + movgt lr, #(1<<31) + orrgt lr, #(1<<16) +.endif + cmn r5, #1 + orrmi lr, r6 + str r1, [r0, #4*24] + str lr, [r0, #4*(32+31)] @ gteFLAG + + pop {r4-r6,pc} + .size gteNCLIP_arm, .-gteNCLIP_arm + + +.macro gteMACtoIR lm + ldr r2, [r0, #4*25] @ gteMAC1 + mov r1, #1<<15 + ldr r12,[r0, #4*(32+31)] @ gteFLAG + cmp r2, r1 + subge r2, r1, #1 + orrge r12, #(1<<31)|(1<<24) +.if \lm + cmp r2, #0 + movlt r2, #0 +.else + cmn r2, r1 + rsblt r2, r1, #0 +.endif + str r2, [r0, #4*9] + ldrd r2, [r0, #4*26] @ gteMAC23 + orrlt r12, #(1<<31)|(1<<24) + cmp r2, r1 + subge r2, r1, #1 + orrge r12, #1<<23 + orrge r12, #1<<31 +.if \lm + cmp r2, #0 + movlt r2, #0 +.else + cmn r2, r1 + rsblt r2, r1, #0 +.endif + orrlt r12, #1<<23 + orrlt r12, #1<<31 + cmp r3, r1 + subge r3, r1, #1 + orrge r12, #1<<22 +.if \lm + cmp r3, #0 + movlt r3, #0 +.else + cmn r3, r1 + rsblt r3, r1, #0 +.endif + orrlt r12, #1<<22 + strd r2, [r0, #4*10] @ gteIR23 + str r12,[r0, #4*(32+31)] @ gteFLAG + bx lr +.endm + +.global gteMACtoIR_lm0 @ r0=CP2 (d,c) +gteMACtoIR_lm0: + gteMACtoIR 0 + .size gteMACtoIR_lm0, .-gteMACtoIR_lm0 + +.global gteMACtoIR_lm1 @ r0=CP2 (d,c) +gteMACtoIR_lm1: + gteMACtoIR 1 + .size gteMACtoIR_lm1, .-gteMACtoIR_lm1 + + +.global gteMACtoIR_lm0_nf @ r0=CP2 (d,c) +gteMACtoIR_lm0_nf: + add r12, r0, #4*25 + ldmia r12, {r1-r3} + ssatx_prep r12, 16 + ssatx r1, r12, 16 + ssatx r2, r12, 16 + ssatx r3, r12, 16 + add r12, r0, #4*9 + stmia r12, {r1-r3} + bx lr + .size gteMACtoIR_lm0_nf, .-gteMACtoIR_lm0_nf + + +.global gteMACtoIR_lm1_nf @ r0=CP2 (d,c) +gteMACtoIR_lm1_nf: + add r12, r0, #4*25 + ldmia r12, {r1-r3} + ssatx0_prep r12, 16 + ssatx0 r1, r12, 16 + ssatx0 r2, r12, 16 + ssatx0 r3, r12, 16 + add r12, r0, #4*9 + stmia r12, {r1-r3} + bx lr + .size gteMACtoIR_lm1_nf, .-gteMACtoIR_lm1_nf + + +.if 0 +.global gteMVMVA_test +gteMVMVA_test: + push {r4-r7,lr} + push {r1} + and r2, r1, #0x18000 @ v + cmp r2, #0x18000 @ v == 3? + addeq r4, r0, #4*9 + addne r3, r0, r2, lsr #12 + ldmeqia r4, {r3-r5} + ldmneia r3, {r4,r5} + lsleq r3, #16 + lsreq r3, #16 + orreq r4, r3, r4, lsl #16 @ r4,r5 = VXYZ(v) + @and r5, #0xffff + add r12, r0, #4*32 + and r3, r1, #0x60000 @ mx + lsr r3, #17 + add r6, r12, r3, lsl #5 + cmp r3, #3 + adreq r6, zeroes + and r2, r1, #0x06000 @ cv + lsr r2, #13 + add r7, r12, r2, lsl #5 + add r7, #4*5 + cmp r2, #3 + adreq r7, zeroes +.if 1 + adr lr, 1f + bne 0f + tst r1, #1<<19 + bne gteMVMVA_part_cv3sh12_arm +0: + and r1, #1<<19 + lsr r1, #19 + b gteMVMVA_part_arm +1: + pop {r1} + tst r1, #1<<10 + adr lr, 0f + beq gteMACtoIR_lm0 + bne gteMACtoIR_lm1 +0: +.else + bl gteMVMVA_part_neon + pop {r1} + and r1, #1<<10 + bl gteMACtoIR_flags_neon +.endif + pop {r4-r7,pc} + +zeroes: + .word 0,0,0,0,0 +.endif + + +@ vim:filetype=armasm + -- cgit v1.2.3 From e028d41faec61a43865cc65b7a5bbc3a87a9adff Mon Sep 17 00:00:00 2001 From: twinaphex Date: Wed, 28 Nov 2012 06:34:54 +0100 Subject: Revert "rename gte_arm.S back to gte_arm.s, fixes compiling on non-Android platforms" This reverts commit 159dc8eed41f86f841d7b0178ed6a015e8019a5e. --- jni/Android.mk | 6 +- libpcsxcore/gte_arm.S | 590 ++++++++++++++++++++++++++++++++++++++++++++++++++ libpcsxcore/gte_arm.s | 590 -------------------------------------------------- 3 files changed, 593 insertions(+), 593 deletions(-) create mode 100644 libpcsxcore/gte_arm.S delete mode 100644 libpcsxcore/gte_arm.s diff --git a/jni/Android.mk b/jni/Android.mk index 81b885d..6be42b1 100644 --- a/jni/Android.mk +++ b/jni/Android.mk @@ -20,14 +20,14 @@ ifeq ($(TARGET_ARCH),arm) LOCAL_ARM_MODE := arm ifeq ($(TARGET_ARCH_EABI),armeabi-v7a) - LOCAL_CFLAGS += -Wa,--defsym,HAVE_ARMV7=1 + LOCAL_CFLAGS += -DHAVE_ARMV7=1 else - LOCAL_CFLAGS += -Wa,--defsym,HAVE_ARMV7=0 + LOCAL_CFLAGS += -DHAVE_ARMV7=0 endif LOCAL_CFLAGS += -DANDROID_ARM - LOCAL_SRC_FILES += ../libpcsxcore/gte_arm.s + LOCAL_SRC_FILES += ../libpcsxcore/gte_arm.S # dynarec LOCAL_SRC_FILES += ../libpcsxcore/new_dynarec/new_dynarec.c ../libpcsxcore/new_dynarec/linkage_arm.S ../libpcsxcore/new_dynarec/emu_if.c ../libpcsxcore/new_dynarec/pcsxmem.c diff --git a/libpcsxcore/gte_arm.S b/libpcsxcore/gte_arm.S new file mode 100644 index 0000000..8700f69 --- /dev/null +++ b/libpcsxcore/gte_arm.S @@ -0,0 +1,590 @@ +/* + * (C) Gražvydas "notaz" Ignotas, 2011 + * + * This work is licensed under the terms of GNU GPL version 2 or later. + * See the COPYING file in the top-level directory. + */ + +/* .equiv HAVE_ARMV7, 1 */ + +.text +.align 2 + +.macro sgnxt16 rd rs +.if HAVE_ARMV7 + sxth \rd, \rs +.else + lsl \rd, \rs, #16 + asr \rd, \rd, #16 +.endif +.endm + +@ prepare work reg for ssatx +@ in: wr reg, bit to saturate to +.macro ssatx_prep wr bit +.if !HAVE_ARMV7 + mov \wr, #(1<<(\bit-1)) +.endif +.endm + +.macro ssatx rd wr bit +.if HAVE_ARMV7 + ssat \rd, #\bit, \rd +.else + cmp \rd, \wr + subge \rd, \wr, #1 + cmn \rd, \wr + rsblt \rd, \wr, #0 +.endif +.endm + +@ prepare work reg for ssatx0 (sat to 0..2^(bit-1)) +@ in: wr reg, bit to saturate to +.macro ssatx0_prep wr bit + mov \wr, #(1<<(\bit-1)) +.endm + +.macro ssatx0 rd wr bit + cmp \rd, \wr + subge \rd, \wr, #1 + cmn \rd, #0 + movlt \rd, #0 +.endm + +.macro usat16_ rd rs +.if HAVE_ARMV7 + usat \rd, #16, \rs +.else + subs \rd, \rs, #0 + movlt \rd, #0 + cmp \rd, #0x10000 + movge \rd, #0x0ff00 + orrge \rd, #0x000ff +.endif +.endm + +.macro udiv_ rd rm rs + lsl \rm, #16 + clz \rd, \rs + lsl \rs, \rs, \rd @ shift up divisor + orr \rd, \rd, #1<<31 + lsr \rd, \rd, \rd +0: + cmp \rm, \rs + subcs \rm, \rs + adcs \rd, \rd, \rd + lsr \rs, #1 + bcc 0b +.endm + +.macro newton_step rcp den zero t1 t2 + umull \t2, \t1, \den, \rcp @ \t2 is dummy + sub \t1, \zero, \t1, lsl #2 + smlal \t2, \rcp, \t1, \rcp +.endm + +.macro udiv_newton rd rm rs t1 t2 t3 t4 + lsl \rd, \rm, #16 + clz \t1, \rs + mov \t2, #0 + lsl \rs, \t1 @ normalize for the algo + mov \rm, #0x4d000000 @ initial estimate ~1.2 + + newton_step \rm, \rs, \t2, \t3, \t4 + newton_step \rm, \rs, \t2, \t3, \t4 + newton_step \rm, \rs, \t2, \t3, \t4 + newton_step \rm, \rs, \t2, \t3, \t4 + + umull \t4, \rd, \rm, \rd + rsb \t2, \t1, #30 @ here t1 is 1..15 + mov \rd, \rd, lsr \t2 +.endm + +@ unsigned divide rd = rm / rs; 16.16 result +@ no div by 0 check +@ in: rm, rs +@ trash: rm rs t* +.macro udiv rd rm rs t1 t2 t3 t4 + @udiv_ \rd, \rm, \rs + udiv_newton \rd, \rm, \rs, \t1, \t2, \t3, \t4 +.endm + +@ calculate RTPS/RTPT MAC values +@ in: r0 context, r8,r9 VXYZ +@ out: r10-r12 MAC123 +@ trash: r1-r7 +.macro do_rtpx_mac + add r1, r0, #4*32 + add r2, r0, #4*(32+5) @ gteTRX + ldmia r1!,{r5-r7} @ gteR1*,gteR2* + ldmia r2, {r10-r12} + smulbb r2, r5, r8 @ gteR11 * gteVX0 + smultt r3, r5, r8 @ gteR12 * gteVY0 + smulbb r4, r6, r9 @ gteR13 * gteVZ0 + qadd r2, r2, r3 + asr r4, r4, #1 @ prevent oflow, lose a bit + add r3, r4, r2, asr #1 + add r10,r10,r3, asr #11 @ gteMAC1 + smultb r2, r6, r8 @ gteR21 * gteVX0 + smulbt r3, r7, r8 @ gteR22 * gteVY0 + smultb r4, r7, r9 @ gteR23 * gteVZ0 + ldmia r1!,{r5-r6} @ gteR3* + qadd r2, r2, r3 + asr r4, r4, #1 + add r3, r4, r2, asr #1 + add r11,r11,r3, asr #11 @ gteMAC2 + @ be more accurate for gteMAC3, since it's also a divider + smulbb r2, r5, r8 @ gteR31 * gteVX0 + smultt r3, r5, r8 @ gteR32 * gteVY0 + smulbb r4, r6, r9 @ gteR33 * gteVZ0 + qadd r2, r2, r3 + asr r3, r4, #31 @ expand to 64bit + adds r1, r2, r4 + adc r3, r2, asr #31 @ 64bit sum in r3,r1 + add r12,r12,r3, lsl #20 + add r12,r12,r1, lsr #12 @ gteMAC3 +.endm + + +.global gteRTPS_nf_arm @ r0=CP2 (d,c), +gteRTPS_nf_arm: + push {r4-r11,lr} + + ldmia r0, {r8,r9} @ VXYZ(0) + do_rtpx_mac + add r1, r0, #4*25 @ gteMAC1 + add r2, r0, #4*17 @ gteSZ1 + stmia r1, {r10-r12} @ gteMAC123 save + ldmia r2, {r3-r5} + add r1, r0, #4*16 @ gteSZ0 + add r2, r0, #4*9 @ gteIR1 + ssatx_prep r6, 16 + usat16_ lr, r12 @ limD + ssatx r10,r6, 16 + ssatx r11,r6, 16 + ssatx r12,r6, 16 + stmia r1, {r3-r5,lr} @ gteSZ* + ldr r3, [r0,#4*(32+26)] @ gteH + stmia r2, {r10,r11,r12} @ gteIR123 save + cmp r3, lr, lsl #1 @ gteH < gteSZ3*2 ? + mov r9, #1<<30 + bhs 1f +.if 1 + udiv r9, r3, lr, r1, r2, r6, r7 +.else + push {r0, r12} + mov r0, r3 + mov r1, lr + bl DIVIDE + mov r9, r0 + pop {r0, r12} +.endif +1: + ldrd r6, [r0,#4*(32+24)] @ gteOFXY + cmp r9, #0x20000 + add r1, r0, #4*12 @ gteSXY0 + movhs r9, #0x20000 + ldmia r1, {r2-r4} + /* quotient */ subhs r9, #1 + mov r2, r6, asr #31 + smlal r6, r2, r10, r9 + stmia r1!,{r3,r4} @ shift gteSXY + mov r3, r7, asr #31 + smlal r7, r3, r11, r9 + lsr r6, #16 + /* gteDQA, gteDQB */ ldrd r10,[r0, #4*(32+27)] + orr r6, r2, lsl #16 @ (gteOFX + gteIR1 * q) >> 16 + ssatx_prep r2, 11 + lsr r7, #16 + /* gteDQB + gteDQA * q */ mla r4, r10, r9, r11 + orr r7, r3, lsl #16 @ (gteOFY + gteIR2 * q) >> 16 + ssatx r6, r2, 11 @ gteSX2 + ssatx r7, r2, 11 @ gteSY2 + strh r6, [r1] + strh r7, [r1, #2] + str r4, [r0,#4*24] @ gteMAC0 + asrs r4, #12 + movmi r4, #0 + cmp r4, #0x1000 @ limH + movgt r4, #0x1000 + str r4, [r0,#4*8] @ gteIR0 + + pop {r4-r11,pc} + .size gteRTPS_nf_arm, .-gteRTPS_nf_arm + + +.global gteRTPT_nf_arm @ r0=CP2 (d,c), +gteRTPT_nf_arm: + ldr r1, [r0, #4*19] @ gteSZ3 + push {r4-r11,lr} + str r1, [r0, #4*16] @ gteSZ0 + mov lr, #0 + +rtpt_arm_loop: + add r1, r0, lr, lsl #1 + ldrd r8, [r1] @ VXYZ(v) + do_rtpx_mac + + ssatx_prep r6, 16 + usat16_ r2, r12 @ limD + add r1, r0, #4*25 @ gteMAC1 + ldr r3, [r0,#4*(32+26)] @ gteH + stmia r1, {r10-r12} @ gteMAC123 save + add r1, r0, #4*17 + ssatx r10,r6, 16 + ssatx r11,r6, 16 + ssatx r12,r6, 16 + str r2, [r1, lr] @ fSZ(v) + cmp r3, r2, lsl #1 @ gteH < gteSZ3*2 ? + mov r9, #1<<30 + bhs 1f +.if 1 + udiv r9, r3, r2, r1, r4, r6, r7 +.else + push {r0, r12, lr} + mov r0, r3 + mov r1, r2 + bl DIVIDE + mov r9, r0 + pop {r0, r12, lr} +.endif +1: cmp r9, #0x20000 + add r1, r0, #4*12 + movhs r9, #0x20000 + ldrd r6, [r0,#4*(32+24)] @ gteOFXY + /* quotient */ subhs r9, #1 + mov r2, r6, asr #31 + smlal r6, r2, r10, r9 + mov r3, r7, asr #31 + smlal r7, r3, r11, r9 + lsr r6, #16 + orr r6, r2, lsl #16 @ (gteOFX + gteIR1 * q) >> 16 + ssatx_prep r2, 11 + lsr r7, #16 + orr r7, r3, lsl #16 @ (gteOFY + gteIR2 * q) >> 16 + ssatx r6, r2, 11 @ gteSX(v) + ssatx r7, r2, 11 @ gteSY(v) + strh r6, [r1, lr]! + add lr, #4 + strh r7, [r1, #2] + cmp lr, #12 + blt rtpt_arm_loop + + ldrd r4, [r0, #4*(32+27)] @ gteDQA, gteDQB + add r1, r0, #4*9 @ gteIR1 + mla r3, r4, r9, r5 @ gteDQB + gteDQA * q + stmia r1, {r10,r11,r12} @ gteIR123 save + + str r3, [r0,#4*24] @ gteMAC0 + asrs r3, #12 + movmi r3, #0 + cmp r3, #0x1000 @ limH + movgt r3, #0x1000 + str r3, [r0,#4*8] @ gteIR0 + + pop {r4-r11,pc} + .size gteRTPT_nf_arm, .-gteRTPT_nf_arm + + +@ note: not std calling convention used +@ r0 = CP2 (d,c) (must preserve) +@ r1 = needs_shift12 +@ r4,r5 = VXYZ(v) packed +@ r6 = &MX11(mx) +@ r7 = &CV1(cv) +.macro mvma_op do_flags + push {r8-r11} + +.if \do_flags + ands r3, r1, #1 @ gteFLAG, shift_need +.else + tst r1, #1 +.endif + ldmia r7, {r7-r9} @ CV123 + ldmia r6!,{r10-r12} @ MX1*,MX2* + asr r1, r7, #20 + lsl r7, #12 @ expand to 64bit + smlalbb r7, r1, r10, r4 @ MX11 * vx + smlaltt r7, r1, r10, r4 @ MX12 * vy + smlalbb r7, r1, r11, r5 @ MX13 * vz + lsrne r7, #12 + orrne r7, r1, lsl #20 @ gteMAC0 +.if \do_flags + asrne r1, #20 + adds r2, r7, #0x80000000 + adcs r1, #0 + orrgt r3, #(1<<30) + orrmi r3, #(1<<31)|(1<<27) + tst r3, #1 @ repeat shift test +.endif + asr r1, r8, #20 + lsl r8, #12 @ expand to 64bit + smlaltb r8, r1, r11, r4 @ MX21 * vx + smlalbt r8, r1, r12, r4 @ MX22 * vy + smlaltb r8, r1, r12, r5 @ MX23 * vz + lsrne r8, #12 + orrne r8, r1, lsl #20 @ gteMAC1 +.if \do_flags + asrne r1, #20 + adds r2, r8, #0x80000000 + adcs r1, #0 + orrgt r3, #(1<<29) + orrmi r3, #(1<<31)|(1<<26) + tst r3, #1 @ repeat shift test +.endif + ldmia r6!,{r10-r11} @ MX3* + asr r1, r9, #20 + lsl r9, #12 @ expand to 64bit + smlalbb r9, r1, r10, r4 @ MX31 * vx + smlaltt r9, r1, r10, r4 @ MX32 * vy + smlalbb r9, r1, r11, r5 @ MX33 * vz + lsrne r9, #12 + orrne r9, r1, lsl #20 @ gteMAC2 +.if \do_flags + asrne r1, #20 + adds r2, r9, #0x80000000 + adcs r1, #0 + orrgt r3, #(1<<28) + orrmi r3, #(1<<31)|(1<<25) + bic r3, #1 +.else + mov r3, #0 +.endif + str r3, [r0, #4*(32+31)] @ gteFLAG + add r1, r0, #4*25 + stmia r1, {r7-r9} + + pop {r8-r11} + bx lr +.endm + +.global gteMVMVA_part_arm +gteMVMVA_part_arm: + mvma_op 1 + .size gteMVMVA_part_arm, .-gteMVMVA_part_arm + +.global gteMVMVA_part_nf_arm +gteMVMVA_part_nf_arm: + mvma_op 0 + .size gteMVMVA_part_nf_arm, .-gteMVMVA_part_nf_arm + +@ common version of MVMVA with cv3 (== 0) and shift12, +@ can't overflow so no gteMAC flags needed +@ note: not std calling convention used +@ r0 = CP2 (d,c) (must preserve) +@ r4,r5 = VXYZ(v) packed +@ r6 = &MX11(mx) +.global gteMVMVA_part_cv3sh12_arm +gteMVMVA_part_cv3sh12_arm: + push {r8-r9} + ldmia r6!,{r7-r9} @ MX1*,MX2* + smulbb r1, r7, r4 @ MX11 * vx + smultt r2, r7, r4 @ MX12 * vy + smulbb r3, r8, r5 @ MX13 * vz + qadd r1, r1, r2 + asr r3, #1 @ prevent oflow, lose a bit + add r1, r3, r1, asr #1 + asr r7, r1, #11 + smultb r1, r8, r4 @ MX21 * vx + smulbt r2, r9, r4 @ MX22 * vy + smultb r3, r9, r5 @ MX23 * vz + qadd r1, r1, r2 + asr r3, #1 + add r1, r3, r1, asr #1 + asr r8, r1, #11 + ldmia r6, {r6,r9} @ MX3* + smulbb r1, r6, r4 @ MX31 * vx + smultt r2, r6, r4 @ MX32 * vy + smulbb r3, r9, r5 @ MX33 * vz + qadd r1, r1, r2 + asr r3, #1 + add r1, r3, r1, asr #1 + asr r9, r1, #11 + add r1, r0, #4*25 + mov r2, #0 + stmia r1, {r7-r9} + str r2, [r0, #4*(32+31)] @ gteFLAG + pop {r8-r9} + bx lr + .size gteMVMVA_part_cv3sh12_arm, .-gteMVMVA_part_cv3sh12_arm + + +.global gteNCLIP_arm @ r0=CP2 (d,c), +gteNCLIP_arm: + push {r4-r6,lr} + ldrsh r4, [r0, #4*12+2] + ldrsh r5, [r0, #4*13+2] + ldrsh r6, [r0, #4*14+2] + ldrsh lr, [r0, #4*12] + ldrsh r2, [r0, #4*13] + sub r12, r4, r5 @ 3: gteSY0 - gteSY1 + sub r5, r5, r6 @ 1: gteSY1 - gteSY2 + smull r1, r5, lr, r5 @ RdLo, RdHi + sub r6, r4 @ 2: gteSY2 - gteSY0 + ldrsh r3, [r0, #4*14] + smlal r1, r5, r2, r6 + mov lr, #0 @ gteFLAG + smlal r1, r5, r3, r12 + mov r6, #1<<31 + orr r6, #1<<15 + movs r2, r1, lsl #1 + adc r5, r5 + cmp r5, #0 +.if HAVE_ARMV7 + movtgt lr, #((1<<31)|(1<<16))>>16 +.else + movgt lr, #(1<<31) + orrgt lr, #(1<<16) +.endif + cmn r5, #1 + orrmi lr, r6 + str r1, [r0, #4*24] + str lr, [r0, #4*(32+31)] @ gteFLAG + + pop {r4-r6,pc} + .size gteNCLIP_arm, .-gteNCLIP_arm + + +.macro gteMACtoIR lm + ldr r2, [r0, #4*25] @ gteMAC1 + mov r1, #1<<15 + ldr r12,[r0, #4*(32+31)] @ gteFLAG + cmp r2, r1 + subge r2, r1, #1 + orrge r12, #(1<<31)|(1<<24) +.if \lm + cmp r2, #0 + movlt r2, #0 +.else + cmn r2, r1 + rsblt r2, r1, #0 +.endif + str r2, [r0, #4*9] + ldrd r2, [r0, #4*26] @ gteMAC23 + orrlt r12, #(1<<31)|(1<<24) + cmp r2, r1 + subge r2, r1, #1 + orrge r12, #1<<23 + orrge r12, #1<<31 +.if \lm + cmp r2, #0 + movlt r2, #0 +.else + cmn r2, r1 + rsblt r2, r1, #0 +.endif + orrlt r12, #1<<23 + orrlt r12, #1<<31 + cmp r3, r1 + subge r3, r1, #1 + orrge r12, #1<<22 +.if \lm + cmp r3, #0 + movlt r3, #0 +.else + cmn r3, r1 + rsblt r3, r1, #0 +.endif + orrlt r12, #1<<22 + strd r2, [r0, #4*10] @ gteIR23 + str r12,[r0, #4*(32+31)] @ gteFLAG + bx lr +.endm + +.global gteMACtoIR_lm0 @ r0=CP2 (d,c) +gteMACtoIR_lm0: + gteMACtoIR 0 + .size gteMACtoIR_lm0, .-gteMACtoIR_lm0 + +.global gteMACtoIR_lm1 @ r0=CP2 (d,c) +gteMACtoIR_lm1: + gteMACtoIR 1 + .size gteMACtoIR_lm1, .-gteMACtoIR_lm1 + + +.global gteMACtoIR_lm0_nf @ r0=CP2 (d,c) +gteMACtoIR_lm0_nf: + add r12, r0, #4*25 + ldmia r12, {r1-r3} + ssatx_prep r12, 16 + ssatx r1, r12, 16 + ssatx r2, r12, 16 + ssatx r3, r12, 16 + add r12, r0, #4*9 + stmia r12, {r1-r3} + bx lr + .size gteMACtoIR_lm0_nf, .-gteMACtoIR_lm0_nf + + +.global gteMACtoIR_lm1_nf @ r0=CP2 (d,c) +gteMACtoIR_lm1_nf: + add r12, r0, #4*25 + ldmia r12, {r1-r3} + ssatx0_prep r12, 16 + ssatx0 r1, r12, 16 + ssatx0 r2, r12, 16 + ssatx0 r3, r12, 16 + add r12, r0, #4*9 + stmia r12, {r1-r3} + bx lr + .size gteMACtoIR_lm1_nf, .-gteMACtoIR_lm1_nf + + +.if 0 +.global gteMVMVA_test +gteMVMVA_test: + push {r4-r7,lr} + push {r1} + and r2, r1, #0x18000 @ v + cmp r2, #0x18000 @ v == 3? + addeq r4, r0, #4*9 + addne r3, r0, r2, lsr #12 + ldmeqia r4, {r3-r5} + ldmneia r3, {r4,r5} + lsleq r3, #16 + lsreq r3, #16 + orreq r4, r3, r4, lsl #16 @ r4,r5 = VXYZ(v) + @and r5, #0xffff + add r12, r0, #4*32 + and r3, r1, #0x60000 @ mx + lsr r3, #17 + add r6, r12, r3, lsl #5 + cmp r3, #3 + adreq r6, zeroes + and r2, r1, #0x06000 @ cv + lsr r2, #13 + add r7, r12, r2, lsl #5 + add r7, #4*5 + cmp r2, #3 + adreq r7, zeroes +.if 1 + adr lr, 1f + bne 0f + tst r1, #1<<19 + bne gteMVMVA_part_cv3sh12_arm +0: + and r1, #1<<19 + lsr r1, #19 + b gteMVMVA_part_arm +1: + pop {r1} + tst r1, #1<<10 + adr lr, 0f + beq gteMACtoIR_lm0 + bne gteMACtoIR_lm1 +0: +.else + bl gteMVMVA_part_neon + pop {r1} + and r1, #1<<10 + bl gteMACtoIR_flags_neon +.endif + pop {r4-r7,pc} + +zeroes: + .word 0,0,0,0,0 +.endif + + +@ vim:filetype=armasm + diff --git a/libpcsxcore/gte_arm.s b/libpcsxcore/gte_arm.s deleted file mode 100644 index 8700f69..0000000 --- a/libpcsxcore/gte_arm.s +++ /dev/null @@ -1,590 +0,0 @@ -/* - * (C) Gražvydas "notaz" Ignotas, 2011 - * - * This work is licensed under the terms of GNU GPL version 2 or later. - * See the COPYING file in the top-level directory. - */ - -/* .equiv HAVE_ARMV7, 1 */ - -.text -.align 2 - -.macro sgnxt16 rd rs -.if HAVE_ARMV7 - sxth \rd, \rs -.else - lsl \rd, \rs, #16 - asr \rd, \rd, #16 -.endif -.endm - -@ prepare work reg for ssatx -@ in: wr reg, bit to saturate to -.macro ssatx_prep wr bit -.if !HAVE_ARMV7 - mov \wr, #(1<<(\bit-1)) -.endif -.endm - -.macro ssatx rd wr bit -.if HAVE_ARMV7 - ssat \rd, #\bit, \rd -.else - cmp \rd, \wr - subge \rd, \wr, #1 - cmn \rd, \wr - rsblt \rd, \wr, #0 -.endif -.endm - -@ prepare work reg for ssatx0 (sat to 0..2^(bit-1)) -@ in: wr reg, bit to saturate to -.macro ssatx0_prep wr bit - mov \wr, #(1<<(\bit-1)) -.endm - -.macro ssatx0 rd wr bit - cmp \rd, \wr - subge \rd, \wr, #1 - cmn \rd, #0 - movlt \rd, #0 -.endm - -.macro usat16_ rd rs -.if HAVE_ARMV7 - usat \rd, #16, \rs -.else - subs \rd, \rs, #0 - movlt \rd, #0 - cmp \rd, #0x10000 - movge \rd, #0x0ff00 - orrge \rd, #0x000ff -.endif -.endm - -.macro udiv_ rd rm rs - lsl \rm, #16 - clz \rd, \rs - lsl \rs, \rs, \rd @ shift up divisor - orr \rd, \rd, #1<<31 - lsr \rd, \rd, \rd -0: - cmp \rm, \rs - subcs \rm, \rs - adcs \rd, \rd, \rd - lsr \rs, #1 - bcc 0b -.endm - -.macro newton_step rcp den zero t1 t2 - umull \t2, \t1, \den, \rcp @ \t2 is dummy - sub \t1, \zero, \t1, lsl #2 - smlal \t2, \rcp, \t1, \rcp -.endm - -.macro udiv_newton rd rm rs t1 t2 t3 t4 - lsl \rd, \rm, #16 - clz \t1, \rs - mov \t2, #0 - lsl \rs, \t1 @ normalize for the algo - mov \rm, #0x4d000000 @ initial estimate ~1.2 - - newton_step \rm, \rs, \t2, \t3, \t4 - newton_step \rm, \rs, \t2, \t3, \t4 - newton_step \rm, \rs, \t2, \t3, \t4 - newton_step \rm, \rs, \t2, \t3, \t4 - - umull \t4, \rd, \rm, \rd - rsb \t2, \t1, #30 @ here t1 is 1..15 - mov \rd, \rd, lsr \t2 -.endm - -@ unsigned divide rd = rm / rs; 16.16 result -@ no div by 0 check -@ in: rm, rs -@ trash: rm rs t* -.macro udiv rd rm rs t1 t2 t3 t4 - @udiv_ \rd, \rm, \rs - udiv_newton \rd, \rm, \rs, \t1, \t2, \t3, \t4 -.endm - -@ calculate RTPS/RTPT MAC values -@ in: r0 context, r8,r9 VXYZ -@ out: r10-r12 MAC123 -@ trash: r1-r7 -.macro do_rtpx_mac - add r1, r0, #4*32 - add r2, r0, #4*(32+5) @ gteTRX - ldmia r1!,{r5-r7} @ gteR1*,gteR2* - ldmia r2, {r10-r12} - smulbb r2, r5, r8 @ gteR11 * gteVX0 - smultt r3, r5, r8 @ gteR12 * gteVY0 - smulbb r4, r6, r9 @ gteR13 * gteVZ0 - qadd r2, r2, r3 - asr r4, r4, #1 @ prevent oflow, lose a bit - add r3, r4, r2, asr #1 - add r10,r10,r3, asr #11 @ gteMAC1 - smultb r2, r6, r8 @ gteR21 * gteVX0 - smulbt r3, r7, r8 @ gteR22 * gteVY0 - smultb r4, r7, r9 @ gteR23 * gteVZ0 - ldmia r1!,{r5-r6} @ gteR3* - qadd r2, r2, r3 - asr r4, r4, #1 - add r3, r4, r2, asr #1 - add r11,r11,r3, asr #11 @ gteMAC2 - @ be more accurate for gteMAC3, since it's also a divider - smulbb r2, r5, r8 @ gteR31 * gteVX0 - smultt r3, r5, r8 @ gteR32 * gteVY0 - smulbb r4, r6, r9 @ gteR33 * gteVZ0 - qadd r2, r2, r3 - asr r3, r4, #31 @ expand to 64bit - adds r1, r2, r4 - adc r3, r2, asr #31 @ 64bit sum in r3,r1 - add r12,r12,r3, lsl #20 - add r12,r12,r1, lsr #12 @ gteMAC3 -.endm - - -.global gteRTPS_nf_arm @ r0=CP2 (d,c), -gteRTPS_nf_arm: - push {r4-r11,lr} - - ldmia r0, {r8,r9} @ VXYZ(0) - do_rtpx_mac - add r1, r0, #4*25 @ gteMAC1 - add r2, r0, #4*17 @ gteSZ1 - stmia r1, {r10-r12} @ gteMAC123 save - ldmia r2, {r3-r5} - add r1, r0, #4*16 @ gteSZ0 - add r2, r0, #4*9 @ gteIR1 - ssatx_prep r6, 16 - usat16_ lr, r12 @ limD - ssatx r10,r6, 16 - ssatx r11,r6, 16 - ssatx r12,r6, 16 - stmia r1, {r3-r5,lr} @ gteSZ* - ldr r3, [r0,#4*(32+26)] @ gteH - stmia r2, {r10,r11,r12} @ gteIR123 save - cmp r3, lr, lsl #1 @ gteH < gteSZ3*2 ? - mov r9, #1<<30 - bhs 1f -.if 1 - udiv r9, r3, lr, r1, r2, r6, r7 -.else - push {r0, r12} - mov r0, r3 - mov r1, lr - bl DIVIDE - mov r9, r0 - pop {r0, r12} -.endif -1: - ldrd r6, [r0,#4*(32+24)] @ gteOFXY - cmp r9, #0x20000 - add r1, r0, #4*12 @ gteSXY0 - movhs r9, #0x20000 - ldmia r1, {r2-r4} - /* quotient */ subhs r9, #1 - mov r2, r6, asr #31 - smlal r6, r2, r10, r9 - stmia r1!,{r3,r4} @ shift gteSXY - mov r3, r7, asr #31 - smlal r7, r3, r11, r9 - lsr r6, #16 - /* gteDQA, gteDQB */ ldrd r10,[r0, #4*(32+27)] - orr r6, r2, lsl #16 @ (gteOFX + gteIR1 * q) >> 16 - ssatx_prep r2, 11 - lsr r7, #16 - /* gteDQB + gteDQA * q */ mla r4, r10, r9, r11 - orr r7, r3, lsl #16 @ (gteOFY + gteIR2 * q) >> 16 - ssatx r6, r2, 11 @ gteSX2 - ssatx r7, r2, 11 @ gteSY2 - strh r6, [r1] - strh r7, [r1, #2] - str r4, [r0,#4*24] @ gteMAC0 - asrs r4, #12 - movmi r4, #0 - cmp r4, #0x1000 @ limH - movgt r4, #0x1000 - str r4, [r0,#4*8] @ gteIR0 - - pop {r4-r11,pc} - .size gteRTPS_nf_arm, .-gteRTPS_nf_arm - - -.global gteRTPT_nf_arm @ r0=CP2 (d,c), -gteRTPT_nf_arm: - ldr r1, [r0, #4*19] @ gteSZ3 - push {r4-r11,lr} - str r1, [r0, #4*16] @ gteSZ0 - mov lr, #0 - -rtpt_arm_loop: - add r1, r0, lr, lsl #1 - ldrd r8, [r1] @ VXYZ(v) - do_rtpx_mac - - ssatx_prep r6, 16 - usat16_ r2, r12 @ limD - add r1, r0, #4*25 @ gteMAC1 - ldr r3, [r0,#4*(32+26)] @ gteH - stmia r1, {r10-r12} @ gteMAC123 save - add r1, r0, #4*17 - ssatx r10,r6, 16 - ssatx r11,r6, 16 - ssatx r12,r6, 16 - str r2, [r1, lr] @ fSZ(v) - cmp r3, r2, lsl #1 @ gteH < gteSZ3*2 ? - mov r9, #1<<30 - bhs 1f -.if 1 - udiv r9, r3, r2, r1, r4, r6, r7 -.else - push {r0, r12, lr} - mov r0, r3 - mov r1, r2 - bl DIVIDE - mov r9, r0 - pop {r0, r12, lr} -.endif -1: cmp r9, #0x20000 - add r1, r0, #4*12 - movhs r9, #0x20000 - ldrd r6, [r0,#4*(32+24)] @ gteOFXY - /* quotient */ subhs r9, #1 - mov r2, r6, asr #31 - smlal r6, r2, r10, r9 - mov r3, r7, asr #31 - smlal r7, r3, r11, r9 - lsr r6, #16 - orr r6, r2, lsl #16 @ (gteOFX + gteIR1 * q) >> 16 - ssatx_prep r2, 11 - lsr r7, #16 - orr r7, r3, lsl #16 @ (gteOFY + gteIR2 * q) >> 16 - ssatx r6, r2, 11 @ gteSX(v) - ssatx r7, r2, 11 @ gteSY(v) - strh r6, [r1, lr]! - add lr, #4 - strh r7, [r1, #2] - cmp lr, #12 - blt rtpt_arm_loop - - ldrd r4, [r0, #4*(32+27)] @ gteDQA, gteDQB - add r1, r0, #4*9 @ gteIR1 - mla r3, r4, r9, r5 @ gteDQB + gteDQA * q - stmia r1, {r10,r11,r12} @ gteIR123 save - - str r3, [r0,#4*24] @ gteMAC0 - asrs r3, #12 - movmi r3, #0 - cmp r3, #0x1000 @ limH - movgt r3, #0x1000 - str r3, [r0,#4*8] @ gteIR0 - - pop {r4-r11,pc} - .size gteRTPT_nf_arm, .-gteRTPT_nf_arm - - -@ note: not std calling convention used -@ r0 = CP2 (d,c) (must preserve) -@ r1 = needs_shift12 -@ r4,r5 = VXYZ(v) packed -@ r6 = &MX11(mx) -@ r7 = &CV1(cv) -.macro mvma_op do_flags - push {r8-r11} - -.if \do_flags - ands r3, r1, #1 @ gteFLAG, shift_need -.else - tst r1, #1 -.endif - ldmia r7, {r7-r9} @ CV123 - ldmia r6!,{r10-r12} @ MX1*,MX2* - asr r1, r7, #20 - lsl r7, #12 @ expand to 64bit - smlalbb r7, r1, r10, r4 @ MX11 * vx - smlaltt r7, r1, r10, r4 @ MX12 * vy - smlalbb r7, r1, r11, r5 @ MX13 * vz - lsrne r7, #12 - orrne r7, r1, lsl #20 @ gteMAC0 -.if \do_flags - asrne r1, #20 - adds r2, r7, #0x80000000 - adcs r1, #0 - orrgt r3, #(1<<30) - orrmi r3, #(1<<31)|(1<<27) - tst r3, #1 @ repeat shift test -.endif - asr r1, r8, #20 - lsl r8, #12 @ expand to 64bit - smlaltb r8, r1, r11, r4 @ MX21 * vx - smlalbt r8, r1, r12, r4 @ MX22 * vy - smlaltb r8, r1, r12, r5 @ MX23 * vz - lsrne r8, #12 - orrne r8, r1, lsl #20 @ gteMAC1 -.if \do_flags - asrne r1, #20 - adds r2, r8, #0x80000000 - adcs r1, #0 - orrgt r3, #(1<<29) - orrmi r3, #(1<<31)|(1<<26) - tst r3, #1 @ repeat shift test -.endif - ldmia r6!,{r10-r11} @ MX3* - asr r1, r9, #20 - lsl r9, #12 @ expand to 64bit - smlalbb r9, r1, r10, r4 @ MX31 * vx - smlaltt r9, r1, r10, r4 @ MX32 * vy - smlalbb r9, r1, r11, r5 @ MX33 * vz - lsrne r9, #12 - orrne r9, r1, lsl #20 @ gteMAC2 -.if \do_flags - asrne r1, #20 - adds r2, r9, #0x80000000 - adcs r1, #0 - orrgt r3, #(1<<28) - orrmi r3, #(1<<31)|(1<<25) - bic r3, #1 -.else - mov r3, #0 -.endif - str r3, [r0, #4*(32+31)] @ gteFLAG - add r1, r0, #4*25 - stmia r1, {r7-r9} - - pop {r8-r11} - bx lr -.endm - -.global gteMVMVA_part_arm -gteMVMVA_part_arm: - mvma_op 1 - .size gteMVMVA_part_arm, .-gteMVMVA_part_arm - -.global gteMVMVA_part_nf_arm -gteMVMVA_part_nf_arm: - mvma_op 0 - .size gteMVMVA_part_nf_arm, .-gteMVMVA_part_nf_arm - -@ common version of MVMVA with cv3 (== 0) and shift12, -@ can't overflow so no gteMAC flags needed -@ note: not std calling convention used -@ r0 = CP2 (d,c) (must preserve) -@ r4,r5 = VXYZ(v) packed -@ r6 = &MX11(mx) -.global gteMVMVA_part_cv3sh12_arm -gteMVMVA_part_cv3sh12_arm: - push {r8-r9} - ldmia r6!,{r7-r9} @ MX1*,MX2* - smulbb r1, r7, r4 @ MX11 * vx - smultt r2, r7, r4 @ MX12 * vy - smulbb r3, r8, r5 @ MX13 * vz - qadd r1, r1, r2 - asr r3, #1 @ prevent oflow, lose a bit - add r1, r3, r1, asr #1 - asr r7, r1, #11 - smultb r1, r8, r4 @ MX21 * vx - smulbt r2, r9, r4 @ MX22 * vy - smultb r3, r9, r5 @ MX23 * vz - qadd r1, r1, r2 - asr r3, #1 - add r1, r3, r1, asr #1 - asr r8, r1, #11 - ldmia r6, {r6,r9} @ MX3* - smulbb r1, r6, r4 @ MX31 * vx - smultt r2, r6, r4 @ MX32 * vy - smulbb r3, r9, r5 @ MX33 * vz - qadd r1, r1, r2 - asr r3, #1 - add r1, r3, r1, asr #1 - asr r9, r1, #11 - add r1, r0, #4*25 - mov r2, #0 - stmia r1, {r7-r9} - str r2, [r0, #4*(32+31)] @ gteFLAG - pop {r8-r9} - bx lr - .size gteMVMVA_part_cv3sh12_arm, .-gteMVMVA_part_cv3sh12_arm - - -.global gteNCLIP_arm @ r0=CP2 (d,c), -gteNCLIP_arm: - push {r4-r6,lr} - ldrsh r4, [r0, #4*12+2] - ldrsh r5, [r0, #4*13+2] - ldrsh r6, [r0, #4*14+2] - ldrsh lr, [r0, #4*12] - ldrsh r2, [r0, #4*13] - sub r12, r4, r5 @ 3: gteSY0 - gteSY1 - sub r5, r5, r6 @ 1: gteSY1 - gteSY2 - smull r1, r5, lr, r5 @ RdLo, RdHi - sub r6, r4 @ 2: gteSY2 - gteSY0 - ldrsh r3, [r0, #4*14] - smlal r1, r5, r2, r6 - mov lr, #0 @ gteFLAG - smlal r1, r5, r3, r12 - mov r6, #1<<31 - orr r6, #1<<15 - movs r2, r1, lsl #1 - adc r5, r5 - cmp r5, #0 -.if HAVE_ARMV7 - movtgt lr, #((1<<31)|(1<<16))>>16 -.else - movgt lr, #(1<<31) - orrgt lr, #(1<<16) -.endif - cmn r5, #1 - orrmi lr, r6 - str r1, [r0, #4*24] - str lr, [r0, #4*(32+31)] @ gteFLAG - - pop {r4-r6,pc} - .size gteNCLIP_arm, .-gteNCLIP_arm - - -.macro gteMACtoIR lm - ldr r2, [r0, #4*25] @ gteMAC1 - mov r1, #1<<15 - ldr r12,[r0, #4*(32+31)] @ gteFLAG - cmp r2, r1 - subge r2, r1, #1 - orrge r12, #(1<<31)|(1<<24) -.if \lm - cmp r2, #0 - movlt r2, #0 -.else - cmn r2, r1 - rsblt r2, r1, #0 -.endif - str r2, [r0, #4*9] - ldrd r2, [r0, #4*26] @ gteMAC23 - orrlt r12, #(1<<31)|(1<<24) - cmp r2, r1 - subge r2, r1, #1 - orrge r12, #1<<23 - orrge r12, #1<<31 -.if \lm - cmp r2, #0 - movlt r2, #0 -.else - cmn r2, r1 - rsblt r2, r1, #0 -.endif - orrlt r12, #1<<23 - orrlt r12, #1<<31 - cmp r3, r1 - subge r3, r1, #1 - orrge r12, #1<<22 -.if \lm - cmp r3, #0 - movlt r3, #0 -.else - cmn r3, r1 - rsblt r3, r1, #0 -.endif - orrlt r12, #1<<22 - strd r2, [r0, #4*10] @ gteIR23 - str r12,[r0, #4*(32+31)] @ gteFLAG - bx lr -.endm - -.global gteMACtoIR_lm0 @ r0=CP2 (d,c) -gteMACtoIR_lm0: - gteMACtoIR 0 - .size gteMACtoIR_lm0, .-gteMACtoIR_lm0 - -.global gteMACtoIR_lm1 @ r0=CP2 (d,c) -gteMACtoIR_lm1: - gteMACtoIR 1 - .size gteMACtoIR_lm1, .-gteMACtoIR_lm1 - - -.global gteMACtoIR_lm0_nf @ r0=CP2 (d,c) -gteMACtoIR_lm0_nf: - add r12, r0, #4*25 - ldmia r12, {r1-r3} - ssatx_prep r12, 16 - ssatx r1, r12, 16 - ssatx r2, r12, 16 - ssatx r3, r12, 16 - add r12, r0, #4*9 - stmia r12, {r1-r3} - bx lr - .size gteMACtoIR_lm0_nf, .-gteMACtoIR_lm0_nf - - -.global gteMACtoIR_lm1_nf @ r0=CP2 (d,c) -gteMACtoIR_lm1_nf: - add r12, r0, #4*25 - ldmia r12, {r1-r3} - ssatx0_prep r12, 16 - ssatx0 r1, r12, 16 - ssatx0 r2, r12, 16 - ssatx0 r3, r12, 16 - add r12, r0, #4*9 - stmia r12, {r1-r3} - bx lr - .size gteMACtoIR_lm1_nf, .-gteMACtoIR_lm1_nf - - -.if 0 -.global gteMVMVA_test -gteMVMVA_test: - push {r4-r7,lr} - push {r1} - and r2, r1, #0x18000 @ v - cmp r2, #0x18000 @ v == 3? - addeq r4, r0, #4*9 - addne r3, r0, r2, lsr #12 - ldmeqia r4, {r3-r5} - ldmneia r3, {r4,r5} - lsleq r3, #16 - lsreq r3, #16 - orreq r4, r3, r4, lsl #16 @ r4,r5 = VXYZ(v) - @and r5, #0xffff - add r12, r0, #4*32 - and r3, r1, #0x60000 @ mx - lsr r3, #17 - add r6, r12, r3, lsl #5 - cmp r3, #3 - adreq r6, zeroes - and r2, r1, #0x06000 @ cv - lsr r2, #13 - add r7, r12, r2, lsl #5 - add r7, #4*5 - cmp r2, #3 - adreq r7, zeroes -.if 1 - adr lr, 1f - bne 0f - tst r1, #1<<19 - bne gteMVMVA_part_cv3sh12_arm -0: - and r1, #1<<19 - lsr r1, #19 - b gteMVMVA_part_arm -1: - pop {r1} - tst r1, #1<<10 - adr lr, 0f - beq gteMACtoIR_lm0 - bne gteMACtoIR_lm1 -0: -.else - bl gteMVMVA_part_neon - pop {r1} - and r1, #1<<10 - bl gteMACtoIR_flags_neon -.endif - pop {r4-r7,pc} - -zeroes: - .word 0,0,0,0,0 -.endif - - -@ vim:filetype=armasm - -- cgit v1.2.3 From b6514bd168106e978a0af0f5043d5da6fd35800a Mon Sep 17 00:00:00 2001 From: twinaphex Date: Wed, 28 Nov 2012 06:35:07 +0100 Subject: Revert "(Android) renamed gte_arm.s to gte_arm.S so it builds on Linux" This reverts commit f4ea2656730fa58df5d340f367ba2a334295c2eb. --- libpcsxcore/gte_arm.S | 590 -------------------------------------------------- libpcsxcore/gte_arm.s | 590 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 590 insertions(+), 590 deletions(-) delete mode 100644 libpcsxcore/gte_arm.S create mode 100644 libpcsxcore/gte_arm.s diff --git a/libpcsxcore/gte_arm.S b/libpcsxcore/gte_arm.S deleted file mode 100644 index 8700f69..0000000 --- a/libpcsxcore/gte_arm.S +++ /dev/null @@ -1,590 +0,0 @@ -/* - * (C) Gražvydas "notaz" Ignotas, 2011 - * - * This work is licensed under the terms of GNU GPL version 2 or later. - * See the COPYING file in the top-level directory. - */ - -/* .equiv HAVE_ARMV7, 1 */ - -.text -.align 2 - -.macro sgnxt16 rd rs -.if HAVE_ARMV7 - sxth \rd, \rs -.else - lsl \rd, \rs, #16 - asr \rd, \rd, #16 -.endif -.endm - -@ prepare work reg for ssatx -@ in: wr reg, bit to saturate to -.macro ssatx_prep wr bit -.if !HAVE_ARMV7 - mov \wr, #(1<<(\bit-1)) -.endif -.endm - -.macro ssatx rd wr bit -.if HAVE_ARMV7 - ssat \rd, #\bit, \rd -.else - cmp \rd, \wr - subge \rd, \wr, #1 - cmn \rd, \wr - rsblt \rd, \wr, #0 -.endif -.endm - -@ prepare work reg for ssatx0 (sat to 0..2^(bit-1)) -@ in: wr reg, bit to saturate to -.macro ssatx0_prep wr bit - mov \wr, #(1<<(\bit-1)) -.endm - -.macro ssatx0 rd wr bit - cmp \rd, \wr - subge \rd, \wr, #1 - cmn \rd, #0 - movlt \rd, #0 -.endm - -.macro usat16_ rd rs -.if HAVE_ARMV7 - usat \rd, #16, \rs -.else - subs \rd, \rs, #0 - movlt \rd, #0 - cmp \rd, #0x10000 - movge \rd, #0x0ff00 - orrge \rd, #0x000ff -.endif -.endm - -.macro udiv_ rd rm rs - lsl \rm, #16 - clz \rd, \rs - lsl \rs, \rs, \rd @ shift up divisor - orr \rd, \rd, #1<<31 - lsr \rd, \rd, \rd -0: - cmp \rm, \rs - subcs \rm, \rs - adcs \rd, \rd, \rd - lsr \rs, #1 - bcc 0b -.endm - -.macro newton_step rcp den zero t1 t2 - umull \t2, \t1, \den, \rcp @ \t2 is dummy - sub \t1, \zero, \t1, lsl #2 - smlal \t2, \rcp, \t1, \rcp -.endm - -.macro udiv_newton rd rm rs t1 t2 t3 t4 - lsl \rd, \rm, #16 - clz \t1, \rs - mov \t2, #0 - lsl \rs, \t1 @ normalize for the algo - mov \rm, #0x4d000000 @ initial estimate ~1.2 - - newton_step \rm, \rs, \t2, \t3, \t4 - newton_step \rm, \rs, \t2, \t3, \t4 - newton_step \rm, \rs, \t2, \t3, \t4 - newton_step \rm, \rs, \t2, \t3, \t4 - - umull \t4, \rd, \rm, \rd - rsb \t2, \t1, #30 @ here t1 is 1..15 - mov \rd, \rd, lsr \t2 -.endm - -@ unsigned divide rd = rm / rs; 16.16 result -@ no div by 0 check -@ in: rm, rs -@ trash: rm rs t* -.macro udiv rd rm rs t1 t2 t3 t4 - @udiv_ \rd, \rm, \rs - udiv_newton \rd, \rm, \rs, \t1, \t2, \t3, \t4 -.endm - -@ calculate RTPS/RTPT MAC values -@ in: r0 context, r8,r9 VXYZ -@ out: r10-r12 MAC123 -@ trash: r1-r7 -.macro do_rtpx_mac - add r1, r0, #4*32 - add r2, r0, #4*(32+5) @ gteTRX - ldmia r1!,{r5-r7} @ gteR1*,gteR2* - ldmia r2, {r10-r12} - smulbb r2, r5, r8 @ gteR11 * gteVX0 - smultt r3, r5, r8 @ gteR12 * gteVY0 - smulbb r4, r6, r9 @ gteR13 * gteVZ0 - qadd r2, r2, r3 - asr r4, r4, #1 @ prevent oflow, lose a bit - add r3, r4, r2, asr #1 - add r10,r10,r3, asr #11 @ gteMAC1 - smultb r2, r6, r8 @ gteR21 * gteVX0 - smulbt r3, r7, r8 @ gteR22 * gteVY0 - smultb r4, r7, r9 @ gteR23 * gteVZ0 - ldmia r1!,{r5-r6} @ gteR3* - qadd r2, r2, r3 - asr r4, r4, #1 - add r3, r4, r2, asr #1 - add r11,r11,r3, asr #11 @ gteMAC2 - @ be more accurate for gteMAC3, since it's also a divider - smulbb r2, r5, r8 @ gteR31 * gteVX0 - smultt r3, r5, r8 @ gteR32 * gteVY0 - smulbb r4, r6, r9 @ gteR33 * gteVZ0 - qadd r2, r2, r3 - asr r3, r4, #31 @ expand to 64bit - adds r1, r2, r4 - adc r3, r2, asr #31 @ 64bit sum in r3,r1 - add r12,r12,r3, lsl #20 - add r12,r12,r1, lsr #12 @ gteMAC3 -.endm - - -.global gteRTPS_nf_arm @ r0=CP2 (d,c), -gteRTPS_nf_arm: - push {r4-r11,lr} - - ldmia r0, {r8,r9} @ VXYZ(0) - do_rtpx_mac - add r1, r0, #4*25 @ gteMAC1 - add r2, r0, #4*17 @ gteSZ1 - stmia r1, {r10-r12} @ gteMAC123 save - ldmia r2, {r3-r5} - add r1, r0, #4*16 @ gteSZ0 - add r2, r0, #4*9 @ gteIR1 - ssatx_prep r6, 16 - usat16_ lr, r12 @ limD - ssatx r10,r6, 16 - ssatx r11,r6, 16 - ssatx r12,r6, 16 - stmia r1, {r3-r5,lr} @ gteSZ* - ldr r3, [r0,#4*(32+26)] @ gteH - stmia r2, {r10,r11,r12} @ gteIR123 save - cmp r3, lr, lsl #1 @ gteH < gteSZ3*2 ? - mov r9, #1<<30 - bhs 1f -.if 1 - udiv r9, r3, lr, r1, r2, r6, r7 -.else - push {r0, r12} - mov r0, r3 - mov r1, lr - bl DIVIDE - mov r9, r0 - pop {r0, r12} -.endif -1: - ldrd r6, [r0,#4*(32+24)] @ gteOFXY - cmp r9, #0x20000 - add r1, r0, #4*12 @ gteSXY0 - movhs r9, #0x20000 - ldmia r1, {r2-r4} - /* quotient */ subhs r9, #1 - mov r2, r6, asr #31 - smlal r6, r2, r10, r9 - stmia r1!,{r3,r4} @ shift gteSXY - mov r3, r7, asr #31 - smlal r7, r3, r11, r9 - lsr r6, #16 - /* gteDQA, gteDQB */ ldrd r10,[r0, #4*(32+27)] - orr r6, r2, lsl #16 @ (gteOFX + gteIR1 * q) >> 16 - ssatx_prep r2, 11 - lsr r7, #16 - /* gteDQB + gteDQA * q */ mla r4, r10, r9, r11 - orr r7, r3, lsl #16 @ (gteOFY + gteIR2 * q) >> 16 - ssatx r6, r2, 11 @ gteSX2 - ssatx r7, r2, 11 @ gteSY2 - strh r6, [r1] - strh r7, [r1, #2] - str r4, [r0,#4*24] @ gteMAC0 - asrs r4, #12 - movmi r4, #0 - cmp r4, #0x1000 @ limH - movgt r4, #0x1000 - str r4, [r0,#4*8] @ gteIR0 - - pop {r4-r11,pc} - .size gteRTPS_nf_arm, .-gteRTPS_nf_arm - - -.global gteRTPT_nf_arm @ r0=CP2 (d,c), -gteRTPT_nf_arm: - ldr r1, [r0, #4*19] @ gteSZ3 - push {r4-r11,lr} - str r1, [r0, #4*16] @ gteSZ0 - mov lr, #0 - -rtpt_arm_loop: - add r1, r0, lr, lsl #1 - ldrd r8, [r1] @ VXYZ(v) - do_rtpx_mac - - ssatx_prep r6, 16 - usat16_ r2, r12 @ limD - add r1, r0, #4*25 @ gteMAC1 - ldr r3, [r0,#4*(32+26)] @ gteH - stmia r1, {r10-r12} @ gteMAC123 save - add r1, r0, #4*17 - ssatx r10,r6, 16 - ssatx r11,r6, 16 - ssatx r12,r6, 16 - str r2, [r1, lr] @ fSZ(v) - cmp r3, r2, lsl #1 @ gteH < gteSZ3*2 ? - mov r9, #1<<30 - bhs 1f -.if 1 - udiv r9, r3, r2, r1, r4, r6, r7 -.else - push {r0, r12, lr} - mov r0, r3 - mov r1, r2 - bl DIVIDE - mov r9, r0 - pop {r0, r12, lr} -.endif -1: cmp r9, #0x20000 - add r1, r0, #4*12 - movhs r9, #0x20000 - ldrd r6, [r0,#4*(32+24)] @ gteOFXY - /* quotient */ subhs r9, #1 - mov r2, r6, asr #31 - smlal r6, r2, r10, r9 - mov r3, r7, asr #31 - smlal r7, r3, r11, r9 - lsr r6, #16 - orr r6, r2, lsl #16 @ (gteOFX + gteIR1 * q) >> 16 - ssatx_prep r2, 11 - lsr r7, #16 - orr r7, r3, lsl #16 @ (gteOFY + gteIR2 * q) >> 16 - ssatx r6, r2, 11 @ gteSX(v) - ssatx r7, r2, 11 @ gteSY(v) - strh r6, [r1, lr]! - add lr, #4 - strh r7, [r1, #2] - cmp lr, #12 - blt rtpt_arm_loop - - ldrd r4, [r0, #4*(32+27)] @ gteDQA, gteDQB - add r1, r0, #4*9 @ gteIR1 - mla r3, r4, r9, r5 @ gteDQB + gteDQA * q - stmia r1, {r10,r11,r12} @ gteIR123 save - - str r3, [r0,#4*24] @ gteMAC0 - asrs r3, #12 - movmi r3, #0 - cmp r3, #0x1000 @ limH - movgt r3, #0x1000 - str r3, [r0,#4*8] @ gteIR0 - - pop {r4-r11,pc} - .size gteRTPT_nf_arm, .-gteRTPT_nf_arm - - -@ note: not std calling convention used -@ r0 = CP2 (d,c) (must preserve) -@ r1 = needs_shift12 -@ r4,r5 = VXYZ(v) packed -@ r6 = &MX11(mx) -@ r7 = &CV1(cv) -.macro mvma_op do_flags - push {r8-r11} - -.if \do_flags - ands r3, r1, #1 @ gteFLAG, shift_need -.else - tst r1, #1 -.endif - ldmia r7, {r7-r9} @ CV123 - ldmia r6!,{r10-r12} @ MX1*,MX2* - asr r1, r7, #20 - lsl r7, #12 @ expand to 64bit - smlalbb r7, r1, r10, r4 @ MX11 * vx - smlaltt r7, r1, r10, r4 @ MX12 * vy - smlalbb r7, r1, r11, r5 @ MX13 * vz - lsrne r7, #12 - orrne r7, r1, lsl #20 @ gteMAC0 -.if \do_flags - asrne r1, #20 - adds r2, r7, #0x80000000 - adcs r1, #0 - orrgt r3, #(1<<30) - orrmi r3, #(1<<31)|(1<<27) - tst r3, #1 @ repeat shift test -.endif - asr r1, r8, #20 - lsl r8, #12 @ expand to 64bit - smlaltb r8, r1, r11, r4 @ MX21 * vx - smlalbt r8, r1, r12, r4 @ MX22 * vy - smlaltb r8, r1, r12, r5 @ MX23 * vz - lsrne r8, #12 - orrne r8, r1, lsl #20 @ gteMAC1 -.if \do_flags - asrne r1, #20 - adds r2, r8, #0x80000000 - adcs r1, #0 - orrgt r3, #(1<<29) - orrmi r3, #(1<<31)|(1<<26) - tst r3, #1 @ repeat shift test -.endif - ldmia r6!,{r10-r11} @ MX3* - asr r1, r9, #20 - lsl r9, #12 @ expand to 64bit - smlalbb r9, r1, r10, r4 @ MX31 * vx - smlaltt r9, r1, r10, r4 @ MX32 * vy - smlalbb r9, r1, r11, r5 @ MX33 * vz - lsrne r9, #12 - orrne r9, r1, lsl #20 @ gteMAC2 -.if \do_flags - asrne r1, #20 - adds r2, r9, #0x80000000 - adcs r1, #0 - orrgt r3, #(1<<28) - orrmi r3, #(1<<31)|(1<<25) - bic r3, #1 -.else - mov r3, #0 -.endif - str r3, [r0, #4*(32+31)] @ gteFLAG - add r1, r0, #4*25 - stmia r1, {r7-r9} - - pop {r8-r11} - bx lr -.endm - -.global gteMVMVA_part_arm -gteMVMVA_part_arm: - mvma_op 1 - .size gteMVMVA_part_arm, .-gteMVMVA_part_arm - -.global gteMVMVA_part_nf_arm -gteMVMVA_part_nf_arm: - mvma_op 0 - .size gteMVMVA_part_nf_arm, .-gteMVMVA_part_nf_arm - -@ common version of MVMVA with cv3 (== 0) and shift12, -@ can't overflow so no gteMAC flags needed -@ note: not std calling convention used -@ r0 = CP2 (d,c) (must preserve) -@ r4,r5 = VXYZ(v) packed -@ r6 = &MX11(mx) -.global gteMVMVA_part_cv3sh12_arm -gteMVMVA_part_cv3sh12_arm: - push {r8-r9} - ldmia r6!,{r7-r9} @ MX1*,MX2* - smulbb r1, r7, r4 @ MX11 * vx - smultt r2, r7, r4 @ MX12 * vy - smulbb r3, r8, r5 @ MX13 * vz - qadd r1, r1, r2 - asr r3, #1 @ prevent oflow, lose a bit - add r1, r3, r1, asr #1 - asr r7, r1, #11 - smultb r1, r8, r4 @ MX21 * vx - smulbt r2, r9, r4 @ MX22 * vy - smultb r3, r9, r5 @ MX23 * vz - qadd r1, r1, r2 - asr r3, #1 - add r1, r3, r1, asr #1 - asr r8, r1, #11 - ldmia r6, {r6,r9} @ MX3* - smulbb r1, r6, r4 @ MX31 * vx - smultt r2, r6, r4 @ MX32 * vy - smulbb r3, r9, r5 @ MX33 * vz - qadd r1, r1, r2 - asr r3, #1 - add r1, r3, r1, asr #1 - asr r9, r1, #11 - add r1, r0, #4*25 - mov r2, #0 - stmia r1, {r7-r9} - str r2, [r0, #4*(32+31)] @ gteFLAG - pop {r8-r9} - bx lr - .size gteMVMVA_part_cv3sh12_arm, .-gteMVMVA_part_cv3sh12_arm - - -.global gteNCLIP_arm @ r0=CP2 (d,c), -gteNCLIP_arm: - push {r4-r6,lr} - ldrsh r4, [r0, #4*12+2] - ldrsh r5, [r0, #4*13+2] - ldrsh r6, [r0, #4*14+2] - ldrsh lr, [r0, #4*12] - ldrsh r2, [r0, #4*13] - sub r12, r4, r5 @ 3: gteSY0 - gteSY1 - sub r5, r5, r6 @ 1: gteSY1 - gteSY2 - smull r1, r5, lr, r5 @ RdLo, RdHi - sub r6, r4 @ 2: gteSY2 - gteSY0 - ldrsh r3, [r0, #4*14] - smlal r1, r5, r2, r6 - mov lr, #0 @ gteFLAG - smlal r1, r5, r3, r12 - mov r6, #1<<31 - orr r6, #1<<15 - movs r2, r1, lsl #1 - adc r5, r5 - cmp r5, #0 -.if HAVE_ARMV7 - movtgt lr, #((1<<31)|(1<<16))>>16 -.else - movgt lr, #(1<<31) - orrgt lr, #(1<<16) -.endif - cmn r5, #1 - orrmi lr, r6 - str r1, [r0, #4*24] - str lr, [r0, #4*(32+31)] @ gteFLAG - - pop {r4-r6,pc} - .size gteNCLIP_arm, .-gteNCLIP_arm - - -.macro gteMACtoIR lm - ldr r2, [r0, #4*25] @ gteMAC1 - mov r1, #1<<15 - ldr r12,[r0, #4*(32+31)] @ gteFLAG - cmp r2, r1 - subge r2, r1, #1 - orrge r12, #(1<<31)|(1<<24) -.if \lm - cmp r2, #0 - movlt r2, #0 -.else - cmn r2, r1 - rsblt r2, r1, #0 -.endif - str r2, [r0, #4*9] - ldrd r2, [r0, #4*26] @ gteMAC23 - orrlt r12, #(1<<31)|(1<<24) - cmp r2, r1 - subge r2, r1, #1 - orrge r12, #1<<23 - orrge r12, #1<<31 -.if \lm - cmp r2, #0 - movlt r2, #0 -.else - cmn r2, r1 - rsblt r2, r1, #0 -.endif - orrlt r12, #1<<23 - orrlt r12, #1<<31 - cmp r3, r1 - subge r3, r1, #1 - orrge r12, #1<<22 -.if \lm - cmp r3, #0 - movlt r3, #0 -.else - cmn r3, r1 - rsblt r3, r1, #0 -.endif - orrlt r12, #1<<22 - strd r2, [r0, #4*10] @ gteIR23 - str r12,[r0, #4*(32+31)] @ gteFLAG - bx lr -.endm - -.global gteMACtoIR_lm0 @ r0=CP2 (d,c) -gteMACtoIR_lm0: - gteMACtoIR 0 - .size gteMACtoIR_lm0, .-gteMACtoIR_lm0 - -.global gteMACtoIR_lm1 @ r0=CP2 (d,c) -gteMACtoIR_lm1: - gteMACtoIR 1 - .size gteMACtoIR_lm1, .-gteMACtoIR_lm1 - - -.global gteMACtoIR_lm0_nf @ r0=CP2 (d,c) -gteMACtoIR_lm0_nf: - add r12, r0, #4*25 - ldmia r12, {r1-r3} - ssatx_prep r12, 16 - ssatx r1, r12, 16 - ssatx r2, r12, 16 - ssatx r3, r12, 16 - add r12, r0, #4*9 - stmia r12, {r1-r3} - bx lr - .size gteMACtoIR_lm0_nf, .-gteMACtoIR_lm0_nf - - -.global gteMACtoIR_lm1_nf @ r0=CP2 (d,c) -gteMACtoIR_lm1_nf: - add r12, r0, #4*25 - ldmia r12, {r1-r3} - ssatx0_prep r12, 16 - ssatx0 r1, r12, 16 - ssatx0 r2, r12, 16 - ssatx0 r3, r12, 16 - add r12, r0, #4*9 - stmia r12, {r1-r3} - bx lr - .size gteMACtoIR_lm1_nf, .-gteMACtoIR_lm1_nf - - -.if 0 -.global gteMVMVA_test -gteMVMVA_test: - push {r4-r7,lr} - push {r1} - and r2, r1, #0x18000 @ v - cmp r2, #0x18000 @ v == 3? - addeq r4, r0, #4*9 - addne r3, r0, r2, lsr #12 - ldmeqia r4, {r3-r5} - ldmneia r3, {r4,r5} - lsleq r3, #16 - lsreq r3, #16 - orreq r4, r3, r4, lsl #16 @ r4,r5 = VXYZ(v) - @and r5, #0xffff - add r12, r0, #4*32 - and r3, r1, #0x60000 @ mx - lsr r3, #17 - add r6, r12, r3, lsl #5 - cmp r3, #3 - adreq r6, zeroes - and r2, r1, #0x06000 @ cv - lsr r2, #13 - add r7, r12, r2, lsl #5 - add r7, #4*5 - cmp r2, #3 - adreq r7, zeroes -.if 1 - adr lr, 1f - bne 0f - tst r1, #1<<19 - bne gteMVMVA_part_cv3sh12_arm -0: - and r1, #1<<19 - lsr r1, #19 - b gteMVMVA_part_arm -1: - pop {r1} - tst r1, #1<<10 - adr lr, 0f - beq gteMACtoIR_lm0 - bne gteMACtoIR_lm1 -0: -.else - bl gteMVMVA_part_neon - pop {r1} - and r1, #1<<10 - bl gteMACtoIR_flags_neon -.endif - pop {r4-r7,pc} - -zeroes: - .word 0,0,0,0,0 -.endif - - -@ vim:filetype=armasm - diff --git a/libpcsxcore/gte_arm.s b/libpcsxcore/gte_arm.s new file mode 100644 index 0000000..8700f69 --- /dev/null +++ b/libpcsxcore/gte_arm.s @@ -0,0 +1,590 @@ +/* + * (C) Gražvydas "notaz" Ignotas, 2011 + * + * This work is licensed under the terms of GNU GPL version 2 or later. + * See the COPYING file in the top-level directory. + */ + +/* .equiv HAVE_ARMV7, 1 */ + +.text +.align 2 + +.macro sgnxt16 rd rs +.if HAVE_ARMV7 + sxth \rd, \rs +.else + lsl \rd, \rs, #16 + asr \rd, \rd, #16 +.endif +.endm + +@ prepare work reg for ssatx +@ in: wr reg, bit to saturate to +.macro ssatx_prep wr bit +.if !HAVE_ARMV7 + mov \wr, #(1<<(\bit-1)) +.endif +.endm + +.macro ssatx rd wr bit +.if HAVE_ARMV7 + ssat \rd, #\bit, \rd +.else + cmp \rd, \wr + subge \rd, \wr, #1 + cmn \rd, \wr + rsblt \rd, \wr, #0 +.endif +.endm + +@ prepare work reg for ssatx0 (sat to 0..2^(bit-1)) +@ in: wr reg, bit to saturate to +.macro ssatx0_prep wr bit + mov \wr, #(1<<(\bit-1)) +.endm + +.macro ssatx0 rd wr bit + cmp \rd, \wr + subge \rd, \wr, #1 + cmn \rd, #0 + movlt \rd, #0 +.endm + +.macro usat16_ rd rs +.if HAVE_ARMV7 + usat \rd, #16, \rs +.else + subs \rd, \rs, #0 + movlt \rd, #0 + cmp \rd, #0x10000 + movge \rd, #0x0ff00 + orrge \rd, #0x000ff +.endif +.endm + +.macro udiv_ rd rm rs + lsl \rm, #16 + clz \rd, \rs + lsl \rs, \rs, \rd @ shift up divisor + orr \rd, \rd, #1<<31 + lsr \rd, \rd, \rd +0: + cmp \rm, \rs + subcs \rm, \rs + adcs \rd, \rd, \rd + lsr \rs, #1 + bcc 0b +.endm + +.macro newton_step rcp den zero t1 t2 + umull \t2, \t1, \den, \rcp @ \t2 is dummy + sub \t1, \zero, \t1, lsl #2 + smlal \t2, \rcp, \t1, \rcp +.endm + +.macro udiv_newton rd rm rs t1 t2 t3 t4 + lsl \rd, \rm, #16 + clz \t1, \rs + mov \t2, #0 + lsl \rs, \t1 @ normalize for the algo + mov \rm, #0x4d000000 @ initial estimate ~1.2 + + newton_step \rm, \rs, \t2, \t3, \t4 + newton_step \rm, \rs, \t2, \t3, \t4 + newton_step \rm, \rs, \t2, \t3, \t4 + newton_step \rm, \rs, \t2, \t3, \t4 + + umull \t4, \rd, \rm, \rd + rsb \t2, \t1, #30 @ here t1 is 1..15 + mov \rd, \rd, lsr \t2 +.endm + +@ unsigned divide rd = rm / rs; 16.16 result +@ no div by 0 check +@ in: rm, rs +@ trash: rm rs t* +.macro udiv rd rm rs t1 t2 t3 t4 + @udiv_ \rd, \rm, \rs + udiv_newton \rd, \rm, \rs, \t1, \t2, \t3, \t4 +.endm + +@ calculate RTPS/RTPT MAC values +@ in: r0 context, r8,r9 VXYZ +@ out: r10-r12 MAC123 +@ trash: r1-r7 +.macro do_rtpx_mac + add r1, r0, #4*32 + add r2, r0, #4*(32+5) @ gteTRX + ldmia r1!,{r5-r7} @ gteR1*,gteR2* + ldmia r2, {r10-r12} + smulbb r2, r5, r8 @ gteR11 * gteVX0 + smultt r3, r5, r8 @ gteR12 * gteVY0 + smulbb r4, r6, r9 @ gteR13 * gteVZ0 + qadd r2, r2, r3 + asr r4, r4, #1 @ prevent oflow, lose a bit + add r3, r4, r2, asr #1 + add r10,r10,r3, asr #11 @ gteMAC1 + smultb r2, r6, r8 @ gteR21 * gteVX0 + smulbt r3, r7, r8 @ gteR22 * gteVY0 + smultb r4, r7, r9 @ gteR23 * gteVZ0 + ldmia r1!,{r5-r6} @ gteR3* + qadd r2, r2, r3 + asr r4, r4, #1 + add r3, r4, r2, asr #1 + add r11,r11,r3, asr #11 @ gteMAC2 + @ be more accurate for gteMAC3, since it's also a divider + smulbb r2, r5, r8 @ gteR31 * gteVX0 + smultt r3, r5, r8 @ gteR32 * gteVY0 + smulbb r4, r6, r9 @ gteR33 * gteVZ0 + qadd r2, r2, r3 + asr r3, r4, #31 @ expand to 64bit + adds r1, r2, r4 + adc r3, r2, asr #31 @ 64bit sum in r3,r1 + add r12,r12,r3, lsl #20 + add r12,r12,r1, lsr #12 @ gteMAC3 +.endm + + +.global gteRTPS_nf_arm @ r0=CP2 (d,c), +gteRTPS_nf_arm: + push {r4-r11,lr} + + ldmia r0, {r8,r9} @ VXYZ(0) + do_rtpx_mac + add r1, r0, #4*25 @ gteMAC1 + add r2, r0, #4*17 @ gteSZ1 + stmia r1, {r10-r12} @ gteMAC123 save + ldmia r2, {r3-r5} + add r1, r0, #4*16 @ gteSZ0 + add r2, r0, #4*9 @ gteIR1 + ssatx_prep r6, 16 + usat16_ lr, r12 @ limD + ssatx r10,r6, 16 + ssatx r11,r6, 16 + ssatx r12,r6, 16 + stmia r1, {r3-r5,lr} @ gteSZ* + ldr r3, [r0,#4*(32+26)] @ gteH + stmia r2, {r10,r11,r12} @ gteIR123 save + cmp r3, lr, lsl #1 @ gteH < gteSZ3*2 ? + mov r9, #1<<30 + bhs 1f +.if 1 + udiv r9, r3, lr, r1, r2, r6, r7 +.else + push {r0, r12} + mov r0, r3 + mov r1, lr + bl DIVIDE + mov r9, r0 + pop {r0, r12} +.endif +1: + ldrd r6, [r0,#4*(32+24)] @ gteOFXY + cmp r9, #0x20000 + add r1, r0, #4*12 @ gteSXY0 + movhs r9, #0x20000 + ldmia r1, {r2-r4} + /* quotient */ subhs r9, #1 + mov r2, r6, asr #31 + smlal r6, r2, r10, r9 + stmia r1!,{r3,r4} @ shift gteSXY + mov r3, r7, asr #31 + smlal r7, r3, r11, r9 + lsr r6, #16 + /* gteDQA, gteDQB */ ldrd r10,[r0, #4*(32+27)] + orr r6, r2, lsl #16 @ (gteOFX + gteIR1 * q) >> 16 + ssatx_prep r2, 11 + lsr r7, #16 + /* gteDQB + gteDQA * q */ mla r4, r10, r9, r11 + orr r7, r3, lsl #16 @ (gteOFY + gteIR2 * q) >> 16 + ssatx r6, r2, 11 @ gteSX2 + ssatx r7, r2, 11 @ gteSY2 + strh r6, [r1] + strh r7, [r1, #2] + str r4, [r0,#4*24] @ gteMAC0 + asrs r4, #12 + movmi r4, #0 + cmp r4, #0x1000 @ limH + movgt r4, #0x1000 + str r4, [r0,#4*8] @ gteIR0 + + pop {r4-r11,pc} + .size gteRTPS_nf_arm, .-gteRTPS_nf_arm + + +.global gteRTPT_nf_arm @ r0=CP2 (d,c), +gteRTPT_nf_arm: + ldr r1, [r0, #4*19] @ gteSZ3 + push {r4-r11,lr} + str r1, [r0, #4*16] @ gteSZ0 + mov lr, #0 + +rtpt_arm_loop: + add r1, r0, lr, lsl #1 + ldrd r8, [r1] @ VXYZ(v) + do_rtpx_mac + + ssatx_prep r6, 16 + usat16_ r2, r12 @ limD + add r1, r0, #4*25 @ gteMAC1 + ldr r3, [r0,#4*(32+26)] @ gteH + stmia r1, {r10-r12} @ gteMAC123 save + add r1, r0, #4*17 + ssatx r10,r6, 16 + ssatx r11,r6, 16 + ssatx r12,r6, 16 + str r2, [r1, lr] @ fSZ(v) + cmp r3, r2, lsl #1 @ gteH < gteSZ3*2 ? + mov r9, #1<<30 + bhs 1f +.if 1 + udiv r9, r3, r2, r1, r4, r6, r7 +.else + push {r0, r12, lr} + mov r0, r3 + mov r1, r2 + bl DIVIDE + mov r9, r0 + pop {r0, r12, lr} +.endif +1: cmp r9, #0x20000 + add r1, r0, #4*12 + movhs r9, #0x20000 + ldrd r6, [r0,#4*(32+24)] @ gteOFXY + /* quotient */ subhs r9, #1 + mov r2, r6, asr #31 + smlal r6, r2, r10, r9 + mov r3, r7, asr #31 + smlal r7, r3, r11, r9 + lsr r6, #16 + orr r6, r2, lsl #16 @ (gteOFX + gteIR1 * q) >> 16 + ssatx_prep r2, 11 + lsr r7, #16 + orr r7, r3, lsl #16 @ (gteOFY + gteIR2 * q) >> 16 + ssatx r6, r2, 11 @ gteSX(v) + ssatx r7, r2, 11 @ gteSY(v) + strh r6, [r1, lr]! + add lr, #4 + strh r7, [r1, #2] + cmp lr, #12 + blt rtpt_arm_loop + + ldrd r4, [r0, #4*(32+27)] @ gteDQA, gteDQB + add r1, r0, #4*9 @ gteIR1 + mla r3, r4, r9, r5 @ gteDQB + gteDQA * q + stmia r1, {r10,r11,r12} @ gteIR123 save + + str r3, [r0,#4*24] @ gteMAC0 + asrs r3, #12 + movmi r3, #0 + cmp r3, #0x1000 @ limH + movgt r3, #0x1000 + str r3, [r0,#4*8] @ gteIR0 + + pop {r4-r11,pc} + .size gteRTPT_nf_arm, .-gteRTPT_nf_arm + + +@ note: not std calling convention used +@ r0 = CP2 (d,c) (must preserve) +@ r1 = needs_shift12 +@ r4,r5 = VXYZ(v) packed +@ r6 = &MX11(mx) +@ r7 = &CV1(cv) +.macro mvma_op do_flags + push {r8-r11} + +.if \do_flags + ands r3, r1, #1 @ gteFLAG, shift_need +.else + tst r1, #1 +.endif + ldmia r7, {r7-r9} @ CV123 + ldmia r6!,{r10-r12} @ MX1*,MX2* + asr r1, r7, #20 + lsl r7, #12 @ expand to 64bit + smlalbb r7, r1, r10, r4 @ MX11 * vx + smlaltt r7, r1, r10, r4 @ MX12 * vy + smlalbb r7, r1, r11, r5 @ MX13 * vz + lsrne r7, #12 + orrne r7, r1, lsl #20 @ gteMAC0 +.if \do_flags + asrne r1, #20 + adds r2, r7, #0x80000000 + adcs r1, #0 + orrgt r3, #(1<<30) + orrmi r3, #(1<<31)|(1<<27) + tst r3, #1 @ repeat shift test +.endif + asr r1, r8, #20 + lsl r8, #12 @ expand to 64bit + smlaltb r8, r1, r11, r4 @ MX21 * vx + smlalbt r8, r1, r12, r4 @ MX22 * vy + smlaltb r8, r1, r12, r5 @ MX23 * vz + lsrne r8, #12 + orrne r8, r1, lsl #20 @ gteMAC1 +.if \do_flags + asrne r1, #20 + adds r2, r8, #0x80000000 + adcs r1, #0 + orrgt r3, #(1<<29) + orrmi r3, #(1<<31)|(1<<26) + tst r3, #1 @ repeat shift test +.endif + ldmia r6!,{r10-r11} @ MX3* + asr r1, r9, #20 + lsl r9, #12 @ expand to 64bit + smlalbb r9, r1, r10, r4 @ MX31 * vx + smlaltt r9, r1, r10, r4 @ MX32 * vy + smlalbb r9, r1, r11, r5 @ MX33 * vz + lsrne r9, #12 + orrne r9, r1, lsl #20 @ gteMAC2 +.if \do_flags + asrne r1, #20 + adds r2, r9, #0x80000000 + adcs r1, #0 + orrgt r3, #(1<<28) + orrmi r3, #(1<<31)|(1<<25) + bic r3, #1 +.else + mov r3, #0 +.endif + str r3, [r0, #4*(32+31)] @ gteFLAG + add r1, r0, #4*25 + stmia r1, {r7-r9} + + pop {r8-r11} + bx lr +.endm + +.global gteMVMVA_part_arm +gteMVMVA_part_arm: + mvma_op 1 + .size gteMVMVA_part_arm, .-gteMVMVA_part_arm + +.global gteMVMVA_part_nf_arm +gteMVMVA_part_nf_arm: + mvma_op 0 + .size gteMVMVA_part_nf_arm, .-gteMVMVA_part_nf_arm + +@ common version of MVMVA with cv3 (== 0) and shift12, +@ can't overflow so no gteMAC flags needed +@ note: not std calling convention used +@ r0 = CP2 (d,c) (must preserve) +@ r4,r5 = VXYZ(v) packed +@ r6 = &MX11(mx) +.global gteMVMVA_part_cv3sh12_arm +gteMVMVA_part_cv3sh12_arm: + push {r8-r9} + ldmia r6!,{r7-r9} @ MX1*,MX2* + smulbb r1, r7, r4 @ MX11 * vx + smultt r2, r7, r4 @ MX12 * vy + smulbb r3, r8, r5 @ MX13 * vz + qadd r1, r1, r2 + asr r3, #1 @ prevent oflow, lose a bit + add r1, r3, r1, asr #1 + asr r7, r1, #11 + smultb r1, r8, r4 @ MX21 * vx + smulbt r2, r9, r4 @ MX22 * vy + smultb r3, r9, r5 @ MX23 * vz + qadd r1, r1, r2 + asr r3, #1 + add r1, r3, r1, asr #1 + asr r8, r1, #11 + ldmia r6, {r6,r9} @ MX3* + smulbb r1, r6, r4 @ MX31 * vx + smultt r2, r6, r4 @ MX32 * vy + smulbb r3, r9, r5 @ MX33 * vz + qadd r1, r1, r2 + asr r3, #1 + add r1, r3, r1, asr #1 + asr r9, r1, #11 + add r1, r0, #4*25 + mov r2, #0 + stmia r1, {r7-r9} + str r2, [r0, #4*(32+31)] @ gteFLAG + pop {r8-r9} + bx lr + .size gteMVMVA_part_cv3sh12_arm, .-gteMVMVA_part_cv3sh12_arm + + +.global gteNCLIP_arm @ r0=CP2 (d,c), +gteNCLIP_arm: + push {r4-r6,lr} + ldrsh r4, [r0, #4*12+2] + ldrsh r5, [r0, #4*13+2] + ldrsh r6, [r0, #4*14+2] + ldrsh lr, [r0, #4*12] + ldrsh r2, [r0, #4*13] + sub r12, r4, r5 @ 3: gteSY0 - gteSY1 + sub r5, r5, r6 @ 1: gteSY1 - gteSY2 + smull r1, r5, lr, r5 @ RdLo, RdHi + sub r6, r4 @ 2: gteSY2 - gteSY0 + ldrsh r3, [r0, #4*14] + smlal r1, r5, r2, r6 + mov lr, #0 @ gteFLAG + smlal r1, r5, r3, r12 + mov r6, #1<<31 + orr r6, #1<<15 + movs r2, r1, lsl #1 + adc r5, r5 + cmp r5, #0 +.if HAVE_ARMV7 + movtgt lr, #((1<<31)|(1<<16))>>16 +.else + movgt lr, #(1<<31) + orrgt lr, #(1<<16) +.endif + cmn r5, #1 + orrmi lr, r6 + str r1, [r0, #4*24] + str lr, [r0, #4*(32+31)] @ gteFLAG + + pop {r4-r6,pc} + .size gteNCLIP_arm, .-gteNCLIP_arm + + +.macro gteMACtoIR lm + ldr r2, [r0, #4*25] @ gteMAC1 + mov r1, #1<<15 + ldr r12,[r0, #4*(32+31)] @ gteFLAG + cmp r2, r1 + subge r2, r1, #1 + orrge r12, #(1<<31)|(1<<24) +.if \lm + cmp r2, #0 + movlt r2, #0 +.else + cmn r2, r1 + rsblt r2, r1, #0 +.endif + str r2, [r0, #4*9] + ldrd r2, [r0, #4*26] @ gteMAC23 + orrlt r12, #(1<<31)|(1<<24) + cmp r2, r1 + subge r2, r1, #1 + orrge r12, #1<<23 + orrge r12, #1<<31 +.if \lm + cmp r2, #0 + movlt r2, #0 +.else + cmn r2, r1 + rsblt r2, r1, #0 +.endif + orrlt r12, #1<<23 + orrlt r12, #1<<31 + cmp r3, r1 + subge r3, r1, #1 + orrge r12, #1<<22 +.if \lm + cmp r3, #0 + movlt r3, #0 +.else + cmn r3, r1 + rsblt r3, r1, #0 +.endif + orrlt r12, #1<<22 + strd r2, [r0, #4*10] @ gteIR23 + str r12,[r0, #4*(32+31)] @ gteFLAG + bx lr +.endm + +.global gteMACtoIR_lm0 @ r0=CP2 (d,c) +gteMACtoIR_lm0: + gteMACtoIR 0 + .size gteMACtoIR_lm0, .-gteMACtoIR_lm0 + +.global gteMACtoIR_lm1 @ r0=CP2 (d,c) +gteMACtoIR_lm1: + gteMACtoIR 1 + .size gteMACtoIR_lm1, .-gteMACtoIR_lm1 + + +.global gteMACtoIR_lm0_nf @ r0=CP2 (d,c) +gteMACtoIR_lm0_nf: + add r12, r0, #4*25 + ldmia r12, {r1-r3} + ssatx_prep r12, 16 + ssatx r1, r12, 16 + ssatx r2, r12, 16 + ssatx r3, r12, 16 + add r12, r0, #4*9 + stmia r12, {r1-r3} + bx lr + .size gteMACtoIR_lm0_nf, .-gteMACtoIR_lm0_nf + + +.global gteMACtoIR_lm1_nf @ r0=CP2 (d,c) +gteMACtoIR_lm1_nf: + add r12, r0, #4*25 + ldmia r12, {r1-r3} + ssatx0_prep r12, 16 + ssatx0 r1, r12, 16 + ssatx0 r2, r12, 16 + ssatx0 r3, r12, 16 + add r12, r0, #4*9 + stmia r12, {r1-r3} + bx lr + .size gteMACtoIR_lm1_nf, .-gteMACtoIR_lm1_nf + + +.if 0 +.global gteMVMVA_test +gteMVMVA_test: + push {r4-r7,lr} + push {r1} + and r2, r1, #0x18000 @ v + cmp r2, #0x18000 @ v == 3? + addeq r4, r0, #4*9 + addne r3, r0, r2, lsr #12 + ldmeqia r4, {r3-r5} + ldmneia r3, {r4,r5} + lsleq r3, #16 + lsreq r3, #16 + orreq r4, r3, r4, lsl #16 @ r4,r5 = VXYZ(v) + @and r5, #0xffff + add r12, r0, #4*32 + and r3, r1, #0x60000 @ mx + lsr r3, #17 + add r6, r12, r3, lsl #5 + cmp r3, #3 + adreq r6, zeroes + and r2, r1, #0x06000 @ cv + lsr r2, #13 + add r7, r12, r2, lsl #5 + add r7, #4*5 + cmp r2, #3 + adreq r7, zeroes +.if 1 + adr lr, 1f + bne 0f + tst r1, #1<<19 + bne gteMVMVA_part_cv3sh12_arm +0: + and r1, #1<<19 + lsr r1, #19 + b gteMVMVA_part_arm +1: + pop {r1} + tst r1, #1<<10 + adr lr, 0f + beq gteMACtoIR_lm0 + bne gteMACtoIR_lm1 +0: +.else + bl gteMVMVA_part_neon + pop {r1} + and r1, #1<<10 + bl gteMACtoIR_flags_neon +.endif + pop {r4-r7,pc} + +zeroes: + .word 0,0,0,0,0 +.endif + + +@ vim:filetype=armasm + -- cgit v1.2.3 From 7f488e2836c5e7503bfb70bbea56a170bf352842 Mon Sep 17 00:00:00 2001 From: Toad King Date: Sun, 2 Dec 2012 14:36:18 -0500 Subject: [LIBRETRO] use SRAM saving routines for memory card. force only one memory card for libretro --- frontend/libretro.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/frontend/libretro.c b/frontend/libretro.c index db13d7a..15041bc 100644 --- a/frontend/libretro.c +++ b/frontend/libretro.c @@ -32,6 +32,10 @@ static int samples_sent, samples_to_send; static int plugins_opened; static int native_rgb565; +/* memory card data */ +extern char Mcd1Data[MCD_SIZE]; +extern char McdDisable[2]; + /* PCSX ReARMed core calls and stuff */ int in_type1, in_type2; int in_a1[2] = { 127, 127 }, in_a2[2] = { 127, 127 }; @@ -295,12 +299,12 @@ unsigned retro_get_region(void) void *retro_get_memory_data(unsigned id) { - return NULL; + return Mcd1Data; } size_t retro_get_memory_size(unsigned id) { - return 0; + return MCD_SIZE; } void retro_reset(void) @@ -387,6 +391,9 @@ void retro_init(void) level = 1; environ_cb(RETRO_ENVIRONMENT_SET_PERFORMANCE_LEVEL, &level); + + McdDisable[0] = 0; + McdDisable[1] = 1; } void retro_deinit(void) -- cgit v1.2.3 From 89d7ac2a566bc0ca8a12bdc6f920d9ee0578163a Mon Sep 17 00:00:00 2001 From: twinaphex Date: Tue, 4 Dec 2012 14:16:34 +0100 Subject: Make RGB565 support into compile-time option - all libretro frontends should support this no matter what --- Makefile | 3 ++- frontend/libretro.c | 12 +++++++----- jni/Android.mk | 2 +- 3 files changed, 10 insertions(+), 7 deletions(-) diff --git a/Makefile b/Makefile index 0c7854d..2ca2fdd 100644 --- a/Makefile +++ b/Makefile @@ -120,7 +120,7 @@ OBJS += plugins/gpu_unai/gpulib_if.o ifeq "$(ARCH)" "arm" OBJS += plugins/gpu_unai/gpu_arm.o endif -plugins/gpu_unai/gpulib_if.o: CFLAGS += -DREARMED -O3 +plugins/gpu_unai/gpulib_if.o: CFLAGS += -DREARMED -O3 CC_LINK = $(CXX) endif @@ -163,6 +163,7 @@ USE_PLUGIN_LIB = 1 endif ifeq "$(PLATFORM)" "libretro" OBJS += frontend/libretro.o +CFLAGS += -DFRONTEND_SUPPORTS_RGB565 endif ifeq "$(USE_PLUGIN_LIB)" "1" diff --git a/frontend/libretro.c b/frontend/libretro.c index 15041bc..49e346b 100644 --- a/frontend/libretro.c +++ b/frontend/libretro.c @@ -30,7 +30,6 @@ static retro_audio_sample_batch_t audio_batch_cb; static void *vout_buf; static int samples_sent, samples_to_send; static int plugins_opened; -static int native_rgb565; /* memory card data */ extern char Mcd1Data[MCD_SIZE]; @@ -51,6 +50,7 @@ static void vout_set_mode(int w, int h, int raw_w, int raw_h, int bpp) { } +#ifdef FRONTEND_SUPPORTS_RGB565 static void convert(void *buf, size_t bytes) { unsigned int i, v, *p = buf; @@ -60,6 +60,7 @@ static void convert(void *buf, size_t bytes) p[i] = (v & 0x001f001f) | ((v >> 1) & 0x7fe07fe0); } } +#endif static void vout_flip(const void *vram, int stride, int bgr24, int w, int h) { @@ -90,8 +91,9 @@ static void vout_flip(const void *vram, int stride, int bgr24, int w, int h) } out: - if (!native_rgb565) - convert(vout_buf, w * h * 2); +#ifndef FRONTEND_SUPPORTS_RGB565 + convert(vout_buf, w * h * 2); +#endif video_cb(vout_buf, w, h, w * 2); pl_rearmed_cbs.flip_cnt++; } @@ -237,11 +239,12 @@ void retro_cheat_set(unsigned index, bool enabled, const char *code) bool retro_load_game(const struct retro_game_info *info) { +#ifdef FRONTEND_SUPPORTS_RGB565 enum retro_pixel_format fmt = RETRO_PIXEL_FORMAT_RGB565; if (environ_cb(RETRO_ENVIRONMENT_SET_PIXEL_FORMAT, &fmt)) { - native_rgb565 = 1; fprintf(stderr, "RGB565 supported, using it\n"); } +#endif if (plugins_opened) { ClosePlugins(); @@ -402,4 +405,3 @@ void retro_deinit(void) free(vout_buf); vout_buf = NULL; } - diff --git a/jni/Android.mk b/jni/Android.mk index 89af335..06b4379 100644 --- a/jni/Android.mk +++ b/jni/Android.mk @@ -89,7 +89,7 @@ LOCAL_SRC_FILES += ../frontend/main.c ../frontend/plugin.c # libretro LOCAL_SRC_FILES += ../frontend/libretro.c -LOCAL_CFLAGS += -O3 -ffast-math -funroll-loops -DNDEBUG -D_FILE_OFFSET_BITS=64 -DHAVE_LIBRETRO -DNO_FRONTEND +LOCAL_CFLAGS += -O3 -ffast-math -funroll-loops -DNDEBUG -D_FILE_OFFSET_BITS=64 -DHAVE_LIBRETRO -DNO_FRONTEND -DFRONTEND_SUPPORTS_RGB565 LOCAL_C_INCLUDES += $(LOCAL_PATH)/../include LOCAL_LDLIBS := -lz -llog -- cgit v1.2.3 From 12990fb369a8b2a63c6a16f45dcce2c7ed93ef5d Mon Sep 17 00:00:00 2001 From: twinaphex Date: Tue, 4 Dec 2012 14:36:01 +0100 Subject: (Libretro) We need to do video_cb in retro_run every frame instead of just once every time the video callback is called - otherwise we will get very bad/skippy framerates. Performance is much improved now in nearly all games. --- frontend/libretro.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/frontend/libretro.c b/frontend/libretro.c index 49e346b..e505804 100644 --- a/frontend/libretro.c +++ b/frontend/libretro.c @@ -62,6 +62,9 @@ static void convert(void *buf, size_t bytes) } #endif +static unsigned game_width; +static unsigned game_height; + static void vout_flip(const void *vram, int stride, int bgr24, int w, int h) { unsigned short *dest = vout_buf; @@ -94,8 +97,8 @@ out: #ifndef FRONTEND_SUPPORTS_RGB565 convert(vout_buf, w * h * 2); #endif - video_cb(vout_buf, w, h, w * 2); - pl_rearmed_cbs.flip_cnt++; + game_width = w; + game_height = h; } static void vout_close(void) @@ -353,6 +356,8 @@ void retro_run(void) psxCpu->Execute(); samples_to_send += 44100 / 60; + video_cb(vout_buf, game_width, game_height, game_width * 2); + pl_rearmed_cbs.flip_cnt++; } void retro_init(void) -- cgit v1.2.3 From 6205c5ce1d4bc2de08559a1753995dbe187c87b6 Mon Sep 17 00:00:00 2001 From: twinaphex Date: Tue, 4 Dec 2012 16:38:01 +0100 Subject: Move flip screen counter increment back to end of flip screen callback --- frontend/libretro.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/libretro.c b/frontend/libretro.c index e505804..180c1d7 100644 --- a/frontend/libretro.c +++ b/frontend/libretro.c @@ -99,6 +99,7 @@ out: #endif game_width = w; game_height = h; + pl_rearmed_cbs.flip_cnt++; } static void vout_close(void) @@ -357,7 +358,6 @@ void retro_run(void) samples_to_send += 44100 / 60; video_cb(vout_buf, game_width, game_height, game_width * 2); - pl_rearmed_cbs.flip_cnt++; } void retro_init(void) -- cgit v1.2.3 From f5cea0386cabbfe8db679bea08975d3289f34032 Mon Sep 17 00:00:00 2001 From: Toad King Date: Tue, 4 Dec 2012 19:26:09 -0500 Subject: initialize blank memory card in libretro --- frontend/libretro.c | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/frontend/libretro.c b/frontend/libretro.c index 180c1d7..6212980 100644 --- a/frontend/libretro.c +++ b/frontend/libretro.c @@ -41,6 +41,39 @@ int in_a1[2] = { 127, 127 }, in_a2[2] = { 127, 127 }; int in_keystate; int in_enable_vibration; +static void init_memcard(char *mcd_data) +{ + unsigned off = 0; + unsigned i; + + memset(mcd_data, 0, MCD_SIZE); + + mcd_data[off++] = 'M'; + mcd_data[off++] = 'C'; + off += 0x7d; + mcd_data[off++] = 0x0e; + + for (i = 0; i < 15; i++) { + mcd_data[off++] = 0xa0; + off += 0x07; + mcd_data[off++] = 0xff; + mcd_data[off++] = 0xff; + off += 0x75; + mcd_data[off++] = 0xa0; + } + + for (i = 0; i < 20; i++) { + mcd_data[off++] = 0xff; + mcd_data[off++] = 0xff; + mcd_data[off++] = 0xff; + mcd_data[off++] = 0xff; + off += 0x04; + mcd_data[off++] = 0xff; + mcd_data[off++] = 0xff; + off += 0x76; + } +} + static int vout_open(void) { return 0; @@ -402,6 +435,7 @@ void retro_init(void) McdDisable[0] = 0; McdDisable[1] = 1; + init_memcard(Mcd1Data); } void retro_deinit(void) -- cgit v1.2.3 From e24064ea9b05d8ff06e8c663c3001f6495a117c4 Mon Sep 17 00:00:00 2001 From: Toad King Date: Tue, 4 Dec 2012 19:26:23 -0500 Subject: update .gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index e6fc06b..2500270 100644 --- a/.gitignore +++ b/.gitignore @@ -10,3 +10,4 @@ config.log frontend/revision.h tools .pcsx/ +obj/ -- cgit v1.2.3 From d02d2725985a6d9748097af0360fb4583cc08ad1 Mon Sep 17 00:00:00 2001 From: twinaphex Date: Thu, 21 Mar 2013 23:04:13 +0100 Subject: Don't compile in null sound driver for libretro and add Makefile.libretro --- Makefile.libretro | 166 ++++++++++++++++++++++++++++++++++++++++++++++++++ plugins/dfsound/out.c | 3 +- 2 files changed, 168 insertions(+), 1 deletion(-) create mode 100644 Makefile.libretro diff --git a/Makefile.libretro b/Makefile.libretro new file mode 100644 index 0000000..6cac460 --- /dev/null +++ b/Makefile.libretro @@ -0,0 +1,166 @@ +# Makefile for PCSX ReARMed (libretro) + +# default stuff goes here, so that config can override +CFLAGS += -Wall -ggdb -Iinclude -ffast-math +ifndef DEBUG +CFLAGS += -O2 -DNDEBUG +endif +CXXFLAGS += $(CFLAGS) +#DRC_DBG = 1 +#PCNT = 1 + +all: target_ plugins_ + +CC = gcc +CXX = g++ +AS = as +CFLAGS += -fPIC -Wno-unused-result +ASFLAGS += +LDFLAGS += +LDLIBS += -lpthread +MAIN_LDFLAGS += -shared -Wl,--no-undefined +MAIN_LDLIBS += -ldl -lm -lz +PLUGIN_CFLAGS += -fPIC + +TARGET = libretro.so +PLATFORM = libretro +BUILTIN_GPU = peops +SOUND_DRIVERS = libretro +PLUGINS = plugins/dfxvideo/gpu_peops.so plugins/gpu_unai/gpu_unai.so + +CC_LINK = $(CC) +LDFLAGS += $(MAIN_LDFLAGS) +LDLIBS += $(MAIN_LDLIBS) +ifdef PCNT +CFLAGS += -DPCNT +endif + +# core +OBJS += libpcsxcore/cdriso.o libpcsxcore/cdrom.o libpcsxcore/cheat.o libpcsxcore/debug.o \ + libpcsxcore/decode_xa.o libpcsxcore/disr3000a.o libpcsxcore/mdec.o \ + libpcsxcore/misc.o libpcsxcore/plugins.o libpcsxcore/ppf.o libpcsxcore/psxbios.o \ + libpcsxcore/psxcommon.o libpcsxcore/psxcounters.o libpcsxcore/psxdma.o libpcsxcore/psxhle.o \ + libpcsxcore/psxhw.o libpcsxcore/psxinterpreter.o libpcsxcore/psxmem.o libpcsxcore/r3000a.o \ + libpcsxcore/sio.o libpcsxcore/socket.o libpcsxcore/spu.o +OBJS += libpcsxcore/gte.o libpcsxcore/gte_nf.o libpcsxcore/gte_divider.o +ifeq "$(ARCH)" "arm" +OBJS += libpcsxcore/gte_arm.o +endif +ifeq "$(HAVE_NEON)" "1" +OBJS += libpcsxcore/gte_neon.o +endif +libpcsxcore/psxbios.o: CFLAGS += -Wno-nonnull + +# dynarec +ifeq "$(USE_DYNAREC)" "1" +OBJS += libpcsxcore/new_dynarec/new_dynarec.o libpcsxcore/new_dynarec/linkage_arm.o +OBJS += libpcsxcore/new_dynarec/pcsxmem.o +else +libpcsxcore/new_dynarec/emu_if.o: CFLAGS += -DDRC_DISABLE +endif +OBJS += libpcsxcore/new_dynarec/emu_if.o +libpcsxcore/new_dynarec/new_dynarec.o: libpcsxcore/new_dynarec/assem_arm.c \ + libpcsxcore/new_dynarec/pcsxmem_inline.c +libpcsxcore/new_dynarec/new_dynarec.o: CFLAGS += -Wno-all -Wno-pointer-sign +ifdef DRC_DBG +libpcsxcore/new_dynarec/emu_if.o: CFLAGS += -D_FILE_OFFSET_BITS=64 +CFLAGS += -DDRC_DBG +endif +ifeq "$(DRC_CACHE_BASE)" "1" +libpcsxcore/new_dynarec/%.o: CFLAGS += -DBASE_ADDR_FIXED=1 +endif + +# spu +OBJS += plugins/dfsound/dma.o plugins/dfsound/freeze.o \ + plugins/dfsound/registers.o plugins/dfsound/spu.o \ + plugins/dfsound/out.o +plugins/dfsound/spu.o: plugins/dfsound/adsr.c plugins/dfsound/reverb.c \ + plugins/dfsound/xa.c +ifeq "$(ARCH)" "arm" +OBJS += plugins/dfsound/arm_utils.o +endif +plugins/dfsound/out.o: CFLAGS += -DHAVE_LIBRETRO + +# builtin gpu +OBJS += plugins/gpulib/gpu.o plugins/gpulib/vout_pl.o +ifeq "$(BUILTIN_GPU)" "neon" +OBJS += plugins/gpu_neon/psx_gpu_if.o plugins/gpu_neon/psx_gpu/psx_gpu_arm_neon.o +plugins/gpu_neon/psx_gpu_if.o: CFLAGS += -DNEON_BUILD -DTEXTURE_CACHE_4BPP -DTEXTURE_CACHE_8BPP +plugins/gpu_neon/psx_gpu_if.o: plugins/gpu_neon/psx_gpu/*.c +endif +ifeq "$(BUILTIN_GPU)" "peops" +# note: code is not safe for strict-aliasing? (Castlevania problems) +plugins/dfxvideo/gpulib_if.o: CFLAGS += -fno-strict-aliasing +plugins/dfxvideo/gpulib_if.o: plugins/dfxvideo/prim.c plugins/dfxvideo/soft.c +OBJS += plugins/dfxvideo/gpulib_if.o +endif +ifeq "$(BUILTIN_GPU)" "unai" +OBJS += plugins/gpu_unai/gpulib_if.o +ifeq "$(ARCH)" "arm" +OBJS += plugins/gpu_unai/gpu_arm.o +endif +plugins/gpu_unai/gpulib_if.o: CFLAGS += -DREARMED -O3 +CC_LINK = $(CXX) +endif + +# cdrcimg +OBJS += plugins/cdrcimg/cdrcimg.o + +# dfinput +OBJS += plugins/dfinput/main.o plugins/dfinput/pad.o plugins/dfinput/guncon.o + +# frontend/gui +OBJS += frontend/cspace.o +ifeq "$(HAVE_NEON)" "1" +OBJS += frontend/cspace_neon.o +else +ifeq "$(ARCH)" "arm" +OBJS += frontend/cspace_arm.o +endif +endif + +CFLAGS += -DFRONTEND_SUPPORTS_RGB565 -DNO_FRONTEND + +# misc +OBJS += frontend/libretro.o frontend/main.o frontend/plugin.o + + +frontend/menu.o frontend/main.o: frontend/revision.h +frontend/libretro.o: frontend/revision.h + +libpcsxcore/gte_nf.o: libpcsxcore/gte.c + $(CC) -c -o $@ $^ $(CFLAGS) -DFLAGLESS + +frontend/revision.h: FORCE + @(git describe || echo) | sed -e 's/.*/#define REV "\0"/' > $@_ + @diff -q $@_ $@ > /dev/null 2>&1 || cp $@_ $@ + @rm $@_ + +%.o: %.S + $(CC) $(CFLAGS) -c $^ -o $@ + + +target_: $(TARGET) + +$(TARGET): $(OBJS) + $(CC_LINK) -o $@ $^ $(LDFLAGS) $(LDLIBS) -Wl,-Map=$@.map + +clean: $(PLAT_CLEAN) clean_plugins + $(RM) $(TARGET) $(OBJS) $(TARGET).map frontend/revision.h + +ifneq ($(PLUGINS),) +plugins_: $(PLUGINS) + +$(PLUGINS): + make -C $(dir $@) + +clean_plugins: + make -C plugins/gpulib/ clean + for dir in $(PLUGINS) ; do \ + $(MAKE) -C $$(dirname $$dir) clean; done +else +plugins_: +clean_plugins: +endif + +.PHONY: all clean target_ plugins_ clean_plugins FORCE diff --git a/plugins/dfsound/out.c b/plugins/dfsound/out.c index 150d718..5ddd3f4 100644 --- a/plugins/dfsound/out.c +++ b/plugins/dfsound/out.c @@ -32,8 +32,9 @@ void SetupSound(void) #endif #ifdef HAVE_LIBRETRO REGISTER_DRIVER(libretro); -#endif +#else REGISTER_DRIVER(none); +#endif } for (i = 0; i < driver_count; i++) -- cgit v1.2.3 From 8045ba8e68a2426d01ce235696b5b9590ad5dc12 Mon Sep 17 00:00:00 2001 From: twinaphex Date: Fri, 22 Mar 2013 00:25:50 +0100 Subject: (libretro) Library version is too long to show in RGUI --- frontend/libretro.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/libretro.c b/frontend/libretro.c index e22ef5b..f916f57 100644 --- a/frontend/libretro.c +++ b/frontend/libretro.c @@ -250,7 +250,7 @@ void retro_get_system_info(struct retro_system_info *info) { memset(info, 0, sizeof(*info)); info->library_name = "PCSX-ReARMed"; - info->library_version = REV; + info->library_version = "r19"; info->valid_extensions = "bin|cue|img|mdf|pbp|cbn"; info->need_fullpath = true; } -- cgit v1.2.3 From 6e1ff5d28d34660d3812c2160f498e0e35ef2483 Mon Sep 17 00:00:00 2001 From: twinaphex Date: Fri, 22 Mar 2013 02:49:08 +0100 Subject: Changes to Makefile.libretro --- Makefile.libretro | 82 +++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 80 insertions(+), 2 deletions(-) diff --git a/Makefile.libretro b/Makefile.libretro index 6cac460..213b409 100644 --- a/Makefile.libretro +++ b/Makefile.libretro @@ -11,14 +11,92 @@ CXXFLAGS += $(CFLAGS) all: target_ plugins_ +ifeq ($(platform),) +platform = unix +ifeq ($(shell uname -a),) + platform = win +else ifneq ($(findstring MINGW,$(shell uname -a)),) + platform = win +else ifneq ($(findstring Darwin,$(shell uname -a)),) + platform = osx +else ifneq ($(findstring win,$(shell uname -a)),) + platform = win +endif +endif + CC = gcc CXX = g++ AS = as -CFLAGS += -fPIC -Wno-unused-result + +ifeq ($(platform), unix) + TARGET := snes9x_next_libretro.so + fpic := -fPIC + SHARED := -shared -Wl,--version-script=libretro/link.T +else ifeq ($(platform), osx) + TARGET := snes9x_next_libretro.dylib + fpic := -fPIC + SHARED := -dynamiclib +else ifeq ($(platform), ios) +ARCH := arm + TARGET := snes9x_next_libretro.dylib + fpic := -fPIC + SHARED := -dynamiclib + +CC = clang -arch armv7 -isysroot $(IOSSDK) +CXX = clang++ -arch armv7 -isysroot $(IOSSDK) +CFLAGS += -mcpu=cortex-a8 -mtune=cortex-a8 -mfpu=neon +ASFLAGS += -mcpu=cortex-a8 -mtune=cortex-a8 -mfpu=neon + HAVE_NEON = 1 + CFLAGS += -DIOS +else ifeq ($(platform), ps3) + TARGET := snes9x_next_libretro_ps3.a + CC = $(CELL_SDK)/host-win32/ppu/bin/ppu-lv2-gcc.exe + AR = $(CELL_SDK)/host-win32/ppu/bin/ppu-lv2-ar.exe + CFLAGS += -DBLARGG_BIG_ENDIAN=1 -D__ppc__ +else ifeq ($(platform), sncps3) + TARGET := snes9x_next_libretro_ps3.a + CC = $(CELL_SDK)/host-win32/sn/bin/ps3ppusnc.exe + AR = $(CELL_SDK)/host-win32/sn/bin/ps3snarl.exe + CFLAGS += -DBLARGG_BIG_ENDIAN=1 -D__ppc__ +else ifeq ($(platform), psl1ght) + TARGET := snes9x_next_libretro_psl1ght.a + CC = $(PS3DEV)/ppu/bin/ppu-gcc$(EXE_EXT) + AR = $(PS3DEV)/ppu/bin/ppu-ar$(EXE_EXT) + CFLAGS += -DBLARGG_BIG_ENDIAN=1 -D__ppc__ +else ifeq ($(platform), psp1) + TARGET := snes9x_next_libretro_psp1.a + CC = psp-gcc$(EXE_EXT) + AR = psp-ar$(EXE_EXT) + CFLAGS += -DPSP -G0 +else ifeq ($(platform), xenon) + TARGET := snes9x_next_libretro_xenon360.a + CC = xenon-gcc$(EXE_EXT) + AR = xenon-ar$(EXE_EXT) + CFLAGS += -D__LIBXENON__ -m32 -D__ppc__ +else ifeq ($(platform), ngc) + TARGET := snes9x_next_libretro_ngc.a + CC = $(DEVKITPPC)/bin/powerpc-eabi-gcc$(EXE_EXT) + AR = $(DEVKITPPC)/bin/powerpc-eabi-ar$(EXE_EXT) + CFLAGS += -DGEKKO -DHW_DOL -mrvl -mcpu=750 -meabi -mhard-float -DBLARGG_BIG_ENDIAN=1 -D__ppc__ +else ifeq ($(platform), wii) + TARGET := snes9x_next_libretro_wii.a + CC = $(DEVKITPPC)/bin/powerpc-eabi-gcc$(EXE_EXT) + AR = $(DEVKITPPC)/bin/powerpc-eabi-ar$(EXE_EXT) + CFLAGS += -DGEKKO -DHW_RVL -mrvl -mcpu=750 -meabi -mhard-float -DBLARGG_BIG_ENDIAN=1 -D__ppc__ +else + TARGET := snes9x_next_retro.dll + CC = gcc + fpic := -fPIC + LD_FLAGS := -fPIC + SHARED := -shared -static-libgcc -static-libstdc++ -s -Wl,--version-script=libretro/link.T + CFLAGS += -D__WIN32__ -D__WIN32_LIBRETRO__ +endif + +CFLAGS += -fPIC ASFLAGS += LDFLAGS += LDLIBS += -lpthread -MAIN_LDFLAGS += -shared -Wl,--no-undefined +MAIN_LDFLAGS += -shared MAIN_LDLIBS += -ldl -lm -lz PLUGIN_CFLAGS += -fPIC -- cgit v1.2.3 From 0286c81237da184cd98afa96bf0215d0e9d2a596 Mon Sep 17 00:00:00 2001 From: twinaphex Date: Fri, 22 Mar 2013 16:51:13 +0100 Subject: (iOS) Use GCC (not working yet) --- Makefile.libretro | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/Makefile.libretro b/Makefile.libretro index 213b409..435a7f7 100644 --- a/Makefile.libretro +++ b/Makefile.libretro @@ -42,10 +42,11 @@ ARCH := arm fpic := -fPIC SHARED := -dynamiclib -CC = clang -arch armv7 -isysroot $(IOSSDK) -CXX = clang++ -arch armv7 -isysroot $(IOSSDK) -CFLAGS += -mcpu=cortex-a8 -mtune=cortex-a8 -mfpu=neon -ASFLAGS += -mcpu=cortex-a8 -mtune=cortex-a8 -mfpu=neon +CC = $(IOSSDK)../../usr/bin/gcc +CXX = $(IOSSDK)../../usr/bin/g++ +CFLAGS += -cpu=cortex-a8 -mfpu=neon +ASFLAGS += -cpu=cortex-a8 -mfpu=neon + HAVE_NEON = 1 CFLAGS += -DIOS else ifeq ($(platform), ps3) -- cgit v1.2.3 From ab82eb7dd3824b66d5cd143141e861403e373308 Mon Sep 17 00:00:00 2001 From: twinaphex Date: Sat, 23 Mar 2013 22:22:10 +0100 Subject: Revert "(iOS) Use GCC (not working yet)" This reverts commit 0286c81237da184cd98afa96bf0215d0e9d2a596. --- Makefile.libretro | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/Makefile.libretro b/Makefile.libretro index 435a7f7..213b409 100644 --- a/Makefile.libretro +++ b/Makefile.libretro @@ -42,11 +42,10 @@ ARCH := arm fpic := -fPIC SHARED := -dynamiclib -CC = $(IOSSDK)../../usr/bin/gcc -CXX = $(IOSSDK)../../usr/bin/g++ -CFLAGS += -cpu=cortex-a8 -mfpu=neon -ASFLAGS += -cpu=cortex-a8 -mfpu=neon - +CC = clang -arch armv7 -isysroot $(IOSSDK) +CXX = clang++ -arch armv7 -isysroot $(IOSSDK) +CFLAGS += -mcpu=cortex-a8 -mtune=cortex-a8 -mfpu=neon +ASFLAGS += -mcpu=cortex-a8 -mtune=cortex-a8 -mfpu=neon HAVE_NEON = 1 CFLAGS += -DIOS else ifeq ($(platform), ps3) -- cgit v1.2.3 From 51014e8756a50a3550a65d0bc96152363e406950 Mon Sep 17 00:00:00 2001 From: CatalystG Date: Sun, 24 Mar 2013 18:09:00 -0400 Subject: Add support for PlayBook/BB10 with libretro --- Makefile.libretro | 32 ++++++-- blackberry_qnx/.cproject | 142 ++++++++++++++++++++++++++++++++++ blackberry_qnx/.project | 84 ++++++++++++++++++++ libpcsxcore/new_dynarec/new_dynarec.c | 4 + libpcsxcore/psxmem.c | 5 ++ 5 files changed, 259 insertions(+), 8 deletions(-) create mode 100644 blackberry_qnx/.cproject create mode 100644 blackberry_qnx/.project diff --git a/Makefile.libretro b/Makefile.libretro index 435a7f7..656b1d2 100644 --- a/Makefile.libretro +++ b/Makefile.libretro @@ -24,9 +24,9 @@ else ifneq ($(findstring win,$(shell uname -a)),) endif endif -CC = gcc -CXX = g++ -AS = as +CC ?= gcc +CXX ?= g++ +AS ?= as ifeq ($(platform), unix) TARGET := snes9x_next_libretro.so @@ -84,6 +84,15 @@ else ifeq ($(platform), wii) CC = $(DEVKITPPC)/bin/powerpc-eabi-gcc$(EXE_EXT) AR = $(DEVKITPPC)/bin/powerpc-eabi-ar$(EXE_EXT) CFLAGS += -DGEKKO -DHW_RVL -mrvl -mcpu=750 -meabi -mhard-float -DBLARGG_BIG_ENDIAN=1 -D__ppc__ +else ifeq ($(platform), qnx) + TARGET := libretro_pcsx_rearmed_qnx.so + HAVE_NEON = 1 + USE_DYNAREC = 1 + DRC_CACHE_BASE = 0 + BUILTIN_GPU = neon + ARCH = arm + CFLAGS += -DBASE_ADDR_FIXED=0 -D__BLACKBERRY_QNX__ -marm -mcpu=cortex-a8 -mtune=cortex-a8 -mfpu=neon -mfloat-abi=softfp + ASFLAGS += -mcpu=cortex-a8 -mfpu=neon -mfloat-abi=softfp else TARGET := snes9x_next_retro.dll CC = gcc @@ -96,16 +105,20 @@ endif CFLAGS += -fPIC ASFLAGS += LDFLAGS += -LDLIBS += -lpthread + +ifneq ($(platform),qnx) + LDLIBS += -lpthread + MAIN_LDLIBS += -ldl +endif MAIN_LDFLAGS += -shared -MAIN_LDLIBS += -ldl -lm -lz +MAIN_LDLIBS += -lm -lz PLUGIN_CFLAGS += -fPIC -TARGET = libretro.so +TARGET ?= libretro.so PLATFORM = libretro -BUILTIN_GPU = peops +BUILTIN_GPU ?= peops SOUND_DRIVERS = libretro -PLUGINS = plugins/dfxvideo/gpu_peops.so plugins/gpu_unai/gpu_unai.so +#PLUGINS = plugins/dfxvideo/gpu_peops.so plugins/gpu_unai/gpu_unai.so CC_LINK = $(CC) LDFLAGS += $(MAIN_LDFLAGS) @@ -217,6 +230,9 @@ frontend/revision.h: FORCE %.o: %.S $(CC) $(CFLAGS) -c $^ -o $@ + +%.o: %.s + $(CC) $(ASFLAGS) -c $^ -o $@ target_: $(TARGET) diff --git a/blackberry_qnx/.cproject b/blackberry_qnx/.cproject new file mode 100644 index 0000000..565f4a9 --- /dev/null +++ b/blackberry_qnx/.cproject @@ -0,0 +1,142 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/blackberry_qnx/.project b/blackberry_qnx/.project new file mode 100644 index 0000000..c8e1e20 --- /dev/null +++ b/blackberry_qnx/.project @@ -0,0 +1,84 @@ + + + pcsx_rearmed + + + + + + org.eclipse.cdt.managedbuilder.core.genmakebuilder + clean,full,incremental, + + + ?name? + + + + org.eclipse.cdt.make.core.append_environment + true + + + org.eclipse.cdt.make.core.autoBuildTarget + all + + + org.eclipse.cdt.make.core.buildArguments + -C .. -f Makefile.libretro platform=qnx + + + org.eclipse.cdt.make.core.buildCommand + make + + + org.eclipse.cdt.make.core.cleanBuildTarget + clean + + + org.eclipse.cdt.make.core.contents + org.eclipse.cdt.make.core.activeConfigSettings + + + org.eclipse.cdt.make.core.enableAutoBuild + false + + + org.eclipse.cdt.make.core.enableCleanBuild + true + + + org.eclipse.cdt.make.core.enableFullBuild + true + + + org.eclipse.cdt.make.core.fullBuildTarget + all + + + org.eclipse.cdt.make.core.stopOnError + true + + + org.eclipse.cdt.make.core.useDefaultBuildCmd + false + + + + + org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder + full,incremental, + + + + + com.qnx.tools.bbt.xml.core.bbtXMLValidationBuilder + + + + + + org.eclipse.cdt.core.cnature + org.eclipse.cdt.managedbuilder.core.managedBuildNature + org.eclipse.cdt.managedbuilder.core.ScannerConfigNature + com.qnx.tools.ide.bbt.core.bbtnature + + diff --git a/libpcsxcore/new_dynarec/new_dynarec.c b/libpcsxcore/new_dynarec/new_dynarec.c index 21c9669..5cdeb96 100644 --- a/libpcsxcore/new_dynarec/new_dynarec.c +++ b/libpcsxcore/new_dynarec/new_dynarec.c @@ -41,6 +41,10 @@ #include "assem_arm.h" #endif +#undef __clear_cache +#define __clear_cache(start,end) msync(start, (size_t)((void*)end - (void*)start), MS_SYNC | MS_CACHE_ONLY | MS_INVALIDATE_ICACHE); + + #define MAXBLOCK 4096 #define MAX_OUTPUT_BLOCK_SIZE 262144 diff --git a/libpcsxcore/psxmem.c b/libpcsxcore/psxmem.c index f12a981..422b485 100644 --- a/libpcsxcore/psxmem.c +++ b/libpcsxcore/psxmem.c @@ -129,8 +129,13 @@ int psxMemInit() { psxM = psxMap(0x80000000, 0x00210000, 1, MAP_TAG_RAM); #ifndef RAM_FIXED +#ifdef __BLACKBERRY_QNX__ + if (psxM == NULL) + psxM = psxMap(0x70000000, 0x00210000, 0, MAP_TAG_RAM); +#else if (psxM == NULL) psxM = psxMap(0x78000000, 0x00210000, 0, MAP_TAG_RAM); +#endif #endif if (psxM == NULL) { SysMessage(_("mapping main RAM failed")); -- cgit v1.2.3 From 0b5d059012a087cd108fe65edaa92e512101fc1a Mon Sep 17 00:00:00 2001 From: CatalystG Date: Sun, 24 Mar 2013 20:24:44 -0400 Subject: Add missing ifdef, move QNX RAM mapping closer to others --- libpcsxcore/new_dynarec/new_dynarec.c | 3 ++- libpcsxcore/psxmem.c | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/libpcsxcore/new_dynarec/new_dynarec.c b/libpcsxcore/new_dynarec/new_dynarec.c index 5cdeb96..a3b766a 100644 --- a/libpcsxcore/new_dynarec/new_dynarec.c +++ b/libpcsxcore/new_dynarec/new_dynarec.c @@ -41,9 +41,10 @@ #include "assem_arm.h" #endif +#ifdef __BLACKBERRY_QNX__ #undef __clear_cache #define __clear_cache(start,end) msync(start, (size_t)((void*)end - (void*)start), MS_SYNC | MS_CACHE_ONLY | MS_INVALIDATE_ICACHE); - +#endif #define MAXBLOCK 4096 #define MAX_OUTPUT_BLOCK_SIZE 262144 diff --git a/libpcsxcore/psxmem.c b/libpcsxcore/psxmem.c index 422b485..62bbe26 100644 --- a/libpcsxcore/psxmem.c +++ b/libpcsxcore/psxmem.c @@ -131,7 +131,7 @@ int psxMemInit() { #ifndef RAM_FIXED #ifdef __BLACKBERRY_QNX__ if (psxM == NULL) - psxM = psxMap(0x70000000, 0x00210000, 0, MAP_TAG_RAM); + psxM = psxMap(0x77000000, 0x00210000, 0, MAP_TAG_RAM); #else if (psxM == NULL) psxM = psxMap(0x78000000, 0x00210000, 0, MAP_TAG_RAM); -- cgit v1.2.3 From 269fec1f8125d51bf482b8e6052e53e0ba8c25e7 Mon Sep 17 00:00:00 2001 From: twinaphex Date: Mon, 25 Mar 2013 06:53:24 +0100 Subject: (Blackberry) Define CC and AR in Makefile - so we can compile from the commandline --- Makefile.libretro | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Makefile.libretro b/Makefile.libretro index bb07fc3..4ec6212 100644 --- a/Makefile.libretro +++ b/Makefile.libretro @@ -79,6 +79,8 @@ else ifeq ($(platform), wii) CFLAGS += -DGEKKO -DHW_RVL -mrvl -mcpu=750 -meabi -mhard-float -DBLARGG_BIG_ENDIAN=1 -D__ppc__ else ifeq ($(platform), qnx) TARGET := libretro_pcsx_rearmed_qnx.so + CC = qcc -Vgcc_ntoarmv7le + AR = qcc -Vgcc_ntoarmv7le HAVE_NEON = 1 USE_DYNAREC = 1 DRC_CACHE_BASE = 0 -- cgit v1.2.3 From 8ac2c35bd816f0a830e3da8f658488516df2a82c Mon Sep 17 00:00:00 2001 From: almostalive Date: Wed, 27 Mar 2013 17:18:22 -0500 Subject: tiny little android neon build fix --- jni/Android.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jni/Android.mk b/jni/Android.mk index 81962e0..72c6738 100644 --- a/jni/Android.mk +++ b/jni/Android.mk @@ -39,7 +39,7 @@ ifeq ($(TARGET_ARCH),arm) else LOCAL_ARM_NEON := true LOCAL_CFLAGS += -DNEON_BUILD -DTEXTURE_CACHE_4BPP -DTEXTURE_CACHE_8BPP - LOCAL_SRC_FILES += ../libpcsxcore/gte_neon.S ../frontend/cspace_neon.s + LOCAL_SRC_FILES += ../libpcsxcore/gte_neon.S ../frontend/cspace_neon.S # gpu LOCAL_SRC_FILES += ../plugins/gpu_neon/psx_gpu_if.c ../plugins/gpu_neon/psx_gpu/psx_gpu_arm_neon.S -- cgit v1.2.3 From de9b02263c0ffa3ccdb41d2fdee3bbf8d1287825 Mon Sep 17 00:00:00 2001 From: twinaphex Date: Mon, 1 Apr 2013 02:59:42 +0200 Subject: (Libretro Makefile) Add ARM target --- Makefile.libretro | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/Makefile.libretro b/Makefile.libretro index 3ff091a..21abefc 100644 --- a/Makefile.libretro +++ b/Makefile.libretro @@ -88,8 +88,17 @@ else ifeq ($(platform), qnx) ARCH = arm CFLAGS += -DBASE_ADDR_FIXED=0 -D__BLACKBERRY_QNX__ -marm -mcpu=cortex-a8 -mtune=cortex-a8 -mfpu=neon -mfloat-abi=softfp ASFLAGS += -mcpu=cortex-a8 -mfpu=neon -mfloat-abi=softfp +else ifeq ($(platform), arm) + TARGET := libretro_pcsx_rearmed.so + HAVE_NEON = 1 + USE_DYNAREC = 1 + DRC_CACHE_BASE = 0 + BUILTIN_GPU = neon + ARCH = arm + CFLAGS += -DBASE_ADDR_FIXED=0 -marm -mcpu=cortex-a8 -mtune=cortex-a8 -mfpu=neon -mfloat-abi=softfp + ASFLAGS += -mcpu=cortex-a8 -mfpu=neon -mfloat-abi=softfp else - TARGET := snes9x_next_retro.dll + TARGET := pcsx_rearmed_retro.dll CC = gcc fpic := -fPIC LD_FLAGS := -fPIC -- cgit v1.2.3 From e56b130002746ea139f3c565d97574670aa533b5 Mon Sep 17 00:00:00 2001 From: twinaphex Date: Mon, 8 Apr 2013 02:03:35 +0200 Subject: (libretro) Update header --- frontend/libretro.h | 88 +++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 76 insertions(+), 12 deletions(-) mode change 100644 => 100755 frontend/libretro.h diff --git a/frontend/libretro.h b/frontend/libretro.h old mode 100644 new mode 100755 index 0c39e6e..b02855a --- a/frontend/libretro.h +++ b/frontend/libretro.h @@ -333,6 +333,8 @@ enum retro_mod RETROKMOD_DUMMY = INT_MAX // Ensure sizeof(enum) == sizeof(int) }; +// If set, this call is not part of the public libretro API yet. It can change or be removed at any time. +#define RETRO_ENVIRONMENT_EXPERIMENTAL 0x10000 // Environment commands. #define RETRO_ENVIRONMENT_SET_ROTATION 1 // const unsigned * -- @@ -348,18 +350,7 @@ enum retro_mod // Boolean value whether or not frontend supports frame duping, // passing NULL to video frame callback. // -#define RETRO_ENVIRONMENT_GET_VARIABLE 4 // struct retro_variable * -- - // Interface to aquire user-defined information from environment - // that cannot feasibly be supported in a multi-system way. - // Mostly used for obscure, - // specific features that the user can tap into when neseccary. - // -#define RETRO_ENVIRONMENT_SET_VARIABLES 5 // const struct retro_variable * -- - // Allows an implementation to signal the environment - // which variables it might want to check for later using GET_VARIABLE. - // 'data' points to an array of retro_variable structs terminated by a { NULL, NULL } element. - // retro_variable::value should contain a human readable description of the key. - // +// Environ 4, 5 are no longer supported (GET_VARIABLE / SET_VARIABLES), and reserved to avoid possible ABI clash. #define RETRO_ENVIRONMENT_SET_MESSAGE 6 // const struct retro_message * -- // Sets a message to be displayed in implementation-specific manner for a certain amount of 'frames'. // Should not be used for trivial messages, which should simply be logged to stderr. @@ -421,7 +412,80 @@ enum retro_mod // Sets an interface which frontend can use to eject and insert disk images. // This is used for games which consist of multiple images and must be manually // swapped out by the user (e.g. PSX). +#define RETRO_ENVIRONMENT_SET_HW_RENDER (14 | RETRO_ENVIRONMENT_EXPERIMENTAL) + // struct retro_hw_render_callback * -- + // NOTE: This call is currently very experimental, and should not be considered part of the public API. + // The interface could be changed or removed at any time. + // Sets an interface to let a libretro core render with hardware acceleration. + // Should be called in retro_load_game(). + // If successful, libretro cores will be able to render to a frontend-provided framebuffer. + // The size of this framebuffer will be at least as large as max_width/max_height provided in get_av_info(). + // If HW rendering is used, pass only RETRO_HW_FRAME_BUFFER_VALID or NULL to retro_video_refresh_t. +#define RETRO_ENVIRONMENT_GET_VARIABLE 15 + // struct retro_variable * -- + // Interface to aquire user-defined information from environment + // that cannot feasibly be supported in a multi-system way. + // 'key' should be set to a key which has already been set by SET_VARIABLES. + // 'data' will be set to a value or NULL. + // +#define RETRO_ENVIRONMENT_SET_VARIABLES 16 + // const struct retro_variable * -- + // Allows an implementation to signal the environment + // which variables it might want to check for later using GET_VARIABLE. + // This allows the frontend to present these variables to a user dynamically. + // This should be called as early as possible (ideally in retro_set_environment). + // + // 'data' points to an array of retro_variable structs terminated by a { NULL, NULL } element. + // retro_variable::key should be namespaced to not collide with other implementations' keys. E.g. A core called 'foo' should use keys named as 'foo_option'. + // retro_variable::value should contain a human readable description of the key as well as a '|' delimited list of expected values. + // The number of possible options should be very limited, i.e. it should be feasible to cycle through options without a keyboard. + // First entry should be treated as a default. + // + // Example entry: + // { "foo_option", "Speed hack coprocessor X; false|true" } + // + // Text before first ';' is description. This ';' must be followed by a space, and followed by a list of possible values split up with '|'. + // Only strings are operated on. The possible values will generally be displayed and stored as-is by the frontend. + // +#define RETRO_ENVIRONMENT_GET_VARIABLE_UPDATE 17 + // bool * -- + // Result is set to true if some variables are updated by + // frontend since last call to RETRO_ENVIRONMENT_GET_VARIABLE. + // Variables should be queried with GET_VARIABLE. + +// Pass this to retro_video_refresh_t if rendering to hardware. +// Passing NULL to retro_video_refresh_t is still a frame dupe as normal. +#define RETRO_HW_FRAME_BUFFER_VALID ((void*)-1) + +// Invalidates the current HW context. +// If called, all GPU resources must be reinitialized. +// Usually called when frontend reinits video driver. +// Also called first time video driver is initialized, allowing libretro core to init resources. +typedef void (*retro_hw_context_reset_t)(void); +// Gets current framebuffer which is to be rendered to. Could change every frame potentially. +typedef uintptr_t (*retro_hw_get_current_framebuffer_t)(void); + +// Get a symbol from HW context. +typedef void (*retro_proc_address_t)(void); +typedef retro_proc_address_t (*retro_hw_get_proc_address_t)(const char *sym); + +enum retro_hw_context_type +{ + RETRO_HW_CONTEXT_NONE = 0, + RETRO_HW_CONTEXT_OPENGL, // OpenGL 2.x. Latest version available before 3.x+. + RETRO_HW_CONTEXT_OPENGLES2, // GLES 2.0 + + RETRO_HW_CONTEXT_DUMMY = INT_MAX +}; +struct retro_hw_render_callback +{ + enum retro_hw_context_type context_type; // Which API to use. Set by libretro core. + retro_hw_context_reset_t context_reset; // Set by libretro core. + retro_hw_get_current_framebuffer_t get_current_framebuffer; // Set by frontend. + retro_hw_get_proc_address_t get_proc_address; // Set by frontend. + bool depth; // Set if render buffers should have depth component attached. +}; // Callback type passed in RETRO_ENVIRONMENT_SET_KEYBOARD_CALLBACK. Called by the frontend in response to keyboard events. // down is set if the key is being pressed, or false if it is being released. -- cgit v1.2.3 From de0e733ec3b6052537301f647e20679a01a1fd61 Mon Sep 17 00:00:00 2001 From: twinaphex Date: Wed, 17 Apr 2013 18:40:14 +0200 Subject: Update target names in Makefile --- Makefile.libretro | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/Makefile.libretro b/Makefile.libretro index 36e0531..7edf54d 100644 --- a/Makefile.libretro +++ b/Makefile.libretro @@ -19,17 +19,19 @@ AS ?= as CC_AS ?= $(CC) CFLAGS ?= +TARGET_NAME := pcsx_rearmed + ifeq ($(platform), unix) - TARGET := pcsx_rearmed_libretro.so + TARGET := $(TARGET_NAME)_libretro.so fpic := -fPIC SHARED := -shared -Wl,--version-script=libretro/link.T else ifeq ($(platform), osx) - TARGET := pcsx_rearmed_libretro.dylib + TARGET := $(TARGET_NAME)_libretro.dylib fpic := -fPIC SHARED := -dynamiclib else ifeq ($(platform), ios) ARCH := arm - TARGET := pcsx_rearmed_libretro.dylib + TARGET := $(TARGET_NAME)_libretro.dylib fpic := -fPIC SHARED := -dynamiclib @@ -43,42 +45,42 @@ ARCH := arm USE_DYNAREC = 1 CFLAGS += -DIOS else ifeq ($(platform), ps3) - TARGET := libretro_pcsx_rearmed_ps3.a + TARGET := libretro_$(TARGET_NAME)_ps3.a CC = $(CELL_SDK)/host-win32/ppu/bin/ppu-lv2-gcc.exe AR = $(CELL_SDK)/host-win32/ppu/bin/ppu-lv2-ar.exe CFLAGS += -DBLARGG_BIG_ENDIAN=1 -D__ppc__ else ifeq ($(platform), sncps3) - TARGET := libretro_pcsx_rearmed_ps3.a + TARGET := libretro_$(TARGET_NAME)_ps3.a CC = $(CELL_SDK)/host-win32/sn/bin/ps3ppusnc.exe AR = $(CELL_SDK)/host-win32/sn/bin/ps3snarl.exe CFLAGS += -DBLARGG_BIG_ENDIAN=1 -D__ppc__ else ifeq ($(platform), psl1ght) - TARGET := libretro_pcsx_rearmed_psl1ght.a + TARGET := libretro_$(TARGET_NAME)_psl1ght.a CC = $(PS3DEV)/ppu/bin/ppu-gcc$(EXE_EXT) AR = $(PS3DEV)/ppu/bin/ppu-ar$(EXE_EXT) CFLAGS += -DBLARGG_BIG_ENDIAN=1 -D__ppc__ else ifeq ($(platform), psp1) - TARGET := libretro_pcsx_rearmed_psp1.a + TARGET := libretro_$(TARGET_NAME)_psp1.a CC = psp-gcc$(EXE_EXT) AR = psp-ar$(EXE_EXT) CFLAGS += -DPSP -G0 else ifeq ($(platform), xenon) - TARGET := libretro_pcsx_rearmed_xenon360.a + TARGET := libretro_$(TARGET_NAME)_xenon360.a CC = xenon-gcc$(EXE_EXT) AR = xenon-ar$(EXE_EXT) CFLAGS += -D__LIBXENON__ -m32 -D__ppc__ else ifeq ($(platform), ngc) - TARGET := libretro_pcsx_rearmed_ngc.a + TARGET := libretro_$(TARGET_NAME)_ngc.a CC = $(DEVKITPPC)/bin/powerpc-eabi-gcc$(EXE_EXT) AR = $(DEVKITPPC)/bin/powerpc-eabi-ar$(EXE_EXT) CFLAGS += -DGEKKO -DHW_DOL -mrvl -mcpu=750 -meabi -mhard-float -DBLARGG_BIG_ENDIAN=1 -D__ppc__ else ifeq ($(platform), wii) - TARGET := libretro_pcsx_rearmed_wii.a + TARGET := libretro_$(TARGET_NAME)_wii.a CC = $(DEVKITPPC)/bin/powerpc-eabi-gcc$(EXE_EXT) AR = $(DEVKITPPC)/bin/powerpc-eabi-ar$(EXE_EXT) CFLAGS += -DGEKKO -DHW_RVL -mrvl -mcpu=750 -meabi -mhard-float -DBLARGG_BIG_ENDIAN=1 -D__ppc__ else ifeq ($(platform), qnx) - TARGET := libretro_pcsx_rearmed_qnx.so + TARGET := libretro_$(TARGET_NAME)_qnx.so CC ?= qcc -Vgcc_ntoarmv7le CC_AS = $(CC) HAVE_NEON = 1 @@ -89,7 +91,7 @@ else ifeq ($(platform), qnx) CFLAGS += -DBASE_ADDR_FIXED=0 -D__BLACKBERRY_QNX__ -marm -mcpu=cortex-a8 -mtune=cortex-a8 -mfpu=neon -mfloat-abi=softfp ASFLAGS += -mcpu=cortex-a8 -mfpu=neon -mfloat-abi=softfp else ifeq ($(platform), arm) - TARGET := pcsx_rearmed_libretro.so + TARGET := $(TARGET_NAME)_libretro.so HAVE_NEON = 1 USE_DYNAREC = 1 DRC_CACHE_BASE = 0 @@ -98,7 +100,7 @@ else ifeq ($(platform), arm) CFLAGS += -marm -mcpu=cortex-a8 -mfpu=neon ASFLAGS += -mcpu=cortex-a8 -mfpu=neon else - TARGET := pcsx_rearmed_retro.dll + TARGET := $(TARGET_NAME)_retro.dll CC = gcc fpic := -fPIC LD_FLAGS := -fPIC -- cgit v1.2.3 From 3d2350ad075a5c07a1fb36229f2c53a295ace62e Mon Sep 17 00:00:00 2001 From: twinaphex Date: Tue, 30 Apr 2013 16:31:52 +0200 Subject: (QNX) Compilation fix --- Makefile.libretro | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Makefile.libretro b/Makefile.libretro index 7edf54d..1ab4cc4 100644 --- a/Makefile.libretro +++ b/Makefile.libretro @@ -81,15 +81,15 @@ else ifeq ($(platform), wii) CFLAGS += -DGEKKO -DHW_RVL -mrvl -mcpu=750 -meabi -mhard-float -DBLARGG_BIG_ENDIAN=1 -D__ppc__ else ifeq ($(platform), qnx) TARGET := libretro_$(TARGET_NAME)_qnx.so - CC ?= qcc -Vgcc_ntoarmv7le + CC = qcc -Vgcc_ntoarmv7le CC_AS = $(CC) HAVE_NEON = 1 USE_DYNAREC = 1 DRC_CACHE_BASE = 0 BUILTIN_GPU = neon ARCH = arm - CFLAGS += -DBASE_ADDR_FIXED=0 -D__BLACKBERRY_QNX__ -marm -mcpu=cortex-a8 -mtune=cortex-a8 -mfpu=neon -mfloat-abi=softfp - ASFLAGS += -mcpu=cortex-a8 -mfpu=neon -mfloat-abi=softfp + CFLAGS += -DBASE_ADDR_FIXED=0 -D__BLACKBERRY_QNX__ -marm -mcpu=cortex-a9 -mtune=cortex-a9 -mfpu=neon -mfloat-abi=softfp + ASFLAGS += -mcpu=cortex-a9 -mfpu=neon -mfloat-abi=softfp else ifeq ($(platform), arm) TARGET := $(TARGET_NAME)_libretro.so HAVE_NEON = 1 -- cgit v1.2.3 From c491fa92b693b60326421094f03b911ee71ef8d7 Mon Sep 17 00:00:00 2001 From: twinaphex Date: Fri, 3 May 2013 17:12:23 +0200 Subject: Add .toc to valid_extensions --- Makefile.libretro | 14 +++++++------- frontend/libretro.c | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/Makefile.libretro b/Makefile.libretro index 1ab4cc4..8e9cdd1 100644 --- a/Makefile.libretro +++ b/Makefile.libretro @@ -45,32 +45,32 @@ ARCH := arm USE_DYNAREC = 1 CFLAGS += -DIOS else ifeq ($(platform), ps3) - TARGET := libretro_$(TARGET_NAME)_ps3.a + TARGET := $(TARGET_NAME)_libretro_ps3.a CC = $(CELL_SDK)/host-win32/ppu/bin/ppu-lv2-gcc.exe AR = $(CELL_SDK)/host-win32/ppu/bin/ppu-lv2-ar.exe CFLAGS += -DBLARGG_BIG_ENDIAN=1 -D__ppc__ else ifeq ($(platform), sncps3) - TARGET := libretro_$(TARGET_NAME)_ps3.a + TARGET := $(TARGET_NAME)_libretro_ps3.a CC = $(CELL_SDK)/host-win32/sn/bin/ps3ppusnc.exe AR = $(CELL_SDK)/host-win32/sn/bin/ps3snarl.exe CFLAGS += -DBLARGG_BIG_ENDIAN=1 -D__ppc__ else ifeq ($(platform), psl1ght) - TARGET := libretro_$(TARGET_NAME)_psl1ght.a + TARGET := $(TARGET_NAME)_libretro_psl1ght.a CC = $(PS3DEV)/ppu/bin/ppu-gcc$(EXE_EXT) AR = $(PS3DEV)/ppu/bin/ppu-ar$(EXE_EXT) CFLAGS += -DBLARGG_BIG_ENDIAN=1 -D__ppc__ else ifeq ($(platform), psp1) - TARGET := libretro_$(TARGET_NAME)_psp1.a + TARGET := $(TARGET_NAME)_libretro_psp1.a CC = psp-gcc$(EXE_EXT) AR = psp-ar$(EXE_EXT) CFLAGS += -DPSP -G0 else ifeq ($(platform), xenon) - TARGET := libretro_$(TARGET_NAME)_xenon360.a + TARGET := $(TARGET_NAME)_libretro_xenon360.a CC = xenon-gcc$(EXE_EXT) AR = xenon-ar$(EXE_EXT) CFLAGS += -D__LIBXENON__ -m32 -D__ppc__ else ifeq ($(platform), ngc) - TARGET := libretro_$(TARGET_NAME)_ngc.a + TARGET := $(TARGET_NAME)_libretro_ngc.a CC = $(DEVKITPPC)/bin/powerpc-eabi-gcc$(EXE_EXT) AR = $(DEVKITPPC)/bin/powerpc-eabi-ar$(EXE_EXT) CFLAGS += -DGEKKO -DHW_DOL -mrvl -mcpu=750 -meabi -mhard-float -DBLARGG_BIG_ENDIAN=1 -D__ppc__ @@ -80,7 +80,7 @@ else ifeq ($(platform), wii) AR = $(DEVKITPPC)/bin/powerpc-eabi-ar$(EXE_EXT) CFLAGS += -DGEKKO -DHW_RVL -mrvl -mcpu=750 -meabi -mhard-float -DBLARGG_BIG_ENDIAN=1 -D__ppc__ else ifeq ($(platform), qnx) - TARGET := libretro_$(TARGET_NAME)_qnx.so + TARGET := $(TARGET_NAME)_libretro_qnx.so CC = qcc -Vgcc_ntoarmv7le CC_AS = $(CC) HAVE_NEON = 1 diff --git a/frontend/libretro.c b/frontend/libretro.c index f916f57..f44cc28 100644 --- a/frontend/libretro.c +++ b/frontend/libretro.c @@ -251,7 +251,7 @@ void retro_get_system_info(struct retro_system_info *info) memset(info, 0, sizeof(*info)); info->library_name = "PCSX-ReARMed"; info->library_version = "r19"; - info->valid_extensions = "bin|cue|img|mdf|pbp|cbn"; + info->valid_extensions = "bin|cue|img|mdf|pbp|toc|cbn"; info->need_fullpath = true; } -- cgit v1.2.3 From 5f8aa603b1f68d4bf4dbd341fed0e31b21f11bde Mon Sep 17 00:00:00 2001 From: twinaphex Date: Sat, 4 May 2013 01:10:21 +0200 Subject: Add hack for broken bin/cue loading right now at startup --- Makefile.libretro | 2 ++ libpcsxcore/cdriso.c | 2 ++ 2 files changed, 4 insertions(+) diff --git a/Makefile.libretro b/Makefile.libretro index 8e9cdd1..db1feb0 100644 --- a/Makefile.libretro +++ b/Makefile.libretro @@ -108,6 +108,8 @@ else CFLAGS += -D__WIN32__ -D__WIN32_LIBRETRO__ endif +CFLAGS += -D__LIBRETRO__ + CFLAGS += -fPIC ifneq ($(platform),qnx) LDLIBS += -lpthread diff --git a/libpcsxcore/cdriso.c b/libpcsxcore/cdriso.c index 9ca4172..24ac891 100644 --- a/libpcsxcore/cdriso.c +++ b/libpcsxcore/cdriso.c @@ -327,6 +327,7 @@ static int parsetoc(const char *isofile) { return -1; } } +#ifndef __LIBRETRO__ // check if it's really a TOC named as a .cue fgets(linebuf, sizeof(linebuf), fi); token = strtok(tmp, " "); @@ -335,6 +336,7 @@ static int parsetoc(const char *isofile) { return -1; } fseek(fi, 0, SEEK_SET); +#endif } memset(&ti, 0, sizeof(ti)); -- cgit v1.2.3 From a1bd06362a0116b4c7445ab49ca582c6b5c954cb Mon Sep 17 00:00:00 2001 From: ToadKing Date: Tue, 7 May 2013 17:17:02 -0400 Subject: add support for mednafen-style .m3u files for multi-disc games --- frontend/libretro.c | 81 +++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 76 insertions(+), 5 deletions(-) diff --git a/frontend/libretro.c b/frontend/libretro.c index f44cc28..b8a5b77 100644 --- a/frontend/libretro.c +++ b/frontend/libretro.c @@ -251,7 +251,7 @@ void retro_get_system_info(struct retro_system_info *info) memset(info, 0, sizeof(*info)); info->library_name = "PCSX-ReARMed"; info->library_version = "r19"; - info->valid_extensions = "bin|cue|img|mdf|pbp|toc|cbn"; + info->valid_extensions = "bin|cue|img|mdf|pbp|toc|cbn|m3u"; info->need_fullpath = true; } @@ -514,9 +514,69 @@ static struct retro_disk_control_callback disk_control = { .add_image_index = disk_add_image_index, }; +// just in case, maybe a win-rt port in the future? +#ifdef _WIN32 +#define SLASH '\\' +#else +#define SLASH '/' +#endif + +static char base_dir[PATH_MAX]; + +static bool read_m3u(const char *file) +{ + char line[PATH_MAX]; + char name[PATH_MAX]; + size_t i = 0; + FILE *f = fopen(file, "r"); + if (!f) + return false; + + while (fgets(line, sizeof(line), f) && i < sizeof(disks) / sizeof(disks[0])) { + if (line[0] == '#') + continue; + char *carrige_return = strchr(line, '\r'); + if (carrige_return) + *carrige_return = '\0'; + char *newline = strchr(line, '\n'); + if (newline) + *newline = '\0'; + + if (line[0] != '\0') + { + snprintf(name, sizeof(name), "%s%c%s", base_dir, SLASH, line); + disks[i++].fname = strdup(name); + } + } + + fclose(f); + return (i != 0); +} + +static void extract_directory(char *buf, const char *path, size_t size) +{ + char *base; + strncpy(buf, path, size - 1); + buf[size - 1] = '\0'; + + base = strrchr(buf, '/'); + if (!base) + base = strrchr(buf, '\\'); + + if (base) + *base = '\0'; + else + { + buf[0] = '.'; + buf[1] = '\0'; + } +} + bool retro_load_game(const struct retro_game_info *info) { size_t i; + bool is_m3u = (strcasestr(info->path, ".m3u") != NULL); + #ifdef FRONTEND_SUPPORTS_RGB565 enum retro_pixel_format fmt = RETRO_PIXEL_FORMAT_RGB565; if (environ_cb(RETRO_ENVIRONMENT_SET_PIXEL_FORMAT, &fmt)) { @@ -543,7 +603,16 @@ bool retro_load_game(const struct retro_game_info *info) } disk_current_index = 0; - disks[0].fname = strdup(info->path); + extract_directory(base_dir, info->path, sizeof(base_dir)); + + if (is_m3u) { + if (!read_m3u(info->path)) { + SysPrintf("failed to read m3u file\n"); + return false; + } + } + else + disks[0].fname = strdup(info->path); set_cd_image(disks[0].fname); @@ -578,9 +647,11 @@ bool retro_load_game(const struct retro_game_info *info) emu_on_new_cd(0); // multidisk images - for (i = 1; i < sizeof(disks) / sizeof(disks[0]) && i < cdrIsoMultidiskCount; i++) { - disks[i].fname = strdup(info->path); - disks[i].internal_index = i; + if (!is_m3u) { + for (i = 1; i < sizeof(disks) / sizeof(disks[0]) && i < cdrIsoMultidiskCount; i++) { + disks[i].fname = strdup(info->path); + disks[i].internal_index = i; + } } return true; -- cgit v1.2.3 From 65ede37b06ca5e59adb10c02850f825c2f431c7b Mon Sep 17 00:00:00 2001 From: ToadKing Date: Tue, 7 May 2013 17:17:46 -0400 Subject: fix bug with memory card files being overwritten with RTC files --- frontend/libretro.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/frontend/libretro.c b/frontend/libretro.c index b8a5b77..9e73fc7 100644 --- a/frontend/libretro.c +++ b/frontend/libretro.c @@ -673,12 +673,18 @@ unsigned retro_get_region(void) void *retro_get_memory_data(unsigned id) { - return Mcd1Data; + if (id == RETRO_MEMORY_SAVE_RAM) + return Mcd1Data; + else + return NULL; } size_t retro_get_memory_size(unsigned id) { - return MCD_SIZE; + if (id == RETRO_MEMORY_SAVE_RAM) + return MCD_SIZE; + else + return 0; } void retro_reset(void) -- cgit v1.2.3 From c8810e871bcb2fe8adc4f5165d83164ef6312b64 Mon Sep 17 00:00:00 2001 From: ToadKing Date: Tue, 7 May 2013 17:52:43 -0400 Subject: implement "add_image_index" correctly --- frontend/libretro.c | 28 +++++++++++++--------------- 1 file changed, 13 insertions(+), 15 deletions(-) diff --git a/frontend/libretro.c b/frontend/libretro.c index 9e73fc7..7a7c2ef 100644 --- a/frontend/libretro.c +++ b/frontend/libretro.c @@ -394,6 +394,7 @@ void retro_cheat_set(unsigned index, bool enabled, const char *code) /* multidisk support */ static bool disk_ejected; static unsigned int disk_current_index; +static unsigned int disk_count; static struct disks_state { char *fname; int internal_index; // for multidisk eboots @@ -463,14 +464,7 @@ static bool disk_set_image_index(unsigned int index) static unsigned int disk_get_num_images(void) { - unsigned int count = 0; - size_t i; - - for (i = 0; i < sizeof(disks) / sizeof(disks[0]); i++) - if (disks[i].fname != NULL) - count++; - - return count; + return disk_count; } static bool disk_replace_image_index(unsigned index, @@ -500,7 +494,10 @@ static bool disk_replace_image_index(unsigned index, static bool disk_add_image_index(void) { - // TODO?? + if (disk_count >= 8) + return false; + + disk_count++; return true; } @@ -527,12 +524,11 @@ static bool read_m3u(const char *file) { char line[PATH_MAX]; char name[PATH_MAX]; - size_t i = 0; FILE *f = fopen(file, "r"); if (!f) return false; - while (fgets(line, sizeof(line), f) && i < sizeof(disks) / sizeof(disks[0])) { + while (fgets(line, sizeof(line), f) && disk_count < sizeof(disks) / sizeof(disks[0])) { if (line[0] == '#') continue; char *carrige_return = strchr(line, '\r'); @@ -545,12 +541,12 @@ static bool read_m3u(const char *file) if (line[0] != '\0') { snprintf(name, sizeof(name), "%s%c%s", base_dir, SLASH, line); - disks[i++].fname = strdup(name); + disks[disk_count++].fname = strdup(name); } } fclose(f); - return (i != 0); + return (disk_count != 0); } static void extract_directory(char *buf, const char *path, size_t size) @@ -610,9 +606,10 @@ bool retro_load_game(const struct retro_game_info *info) SysPrintf("failed to read m3u file\n"); return false; } - } - else + } else { + disk_count = 1; disks[0].fname = strdup(info->path); + } set_cd_image(disks[0].fname); @@ -648,6 +645,7 @@ bool retro_load_game(const struct retro_game_info *info) // multidisk images if (!is_m3u) { + disk_count = cdrIsoMultidiskCount < 8 ? cdrIsoMultidiskCount : 8; for (i = 1; i < sizeof(disks) / sizeof(disks[0]) && i < cdrIsoMultidiskCount; i++) { disks[i].fname = strdup(info->path); disks[i].internal_index = i; -- cgit v1.2.3 From 5cdb2a3c8c6d53dd47257101d577f1fb43c2f459 Mon Sep 17 00:00:00 2001 From: twinaphex Date: Sat, 18 May 2013 03:42:37 +0200 Subject: (iOS) Standardize target name --- Makefile.libretro | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile.libretro b/Makefile.libretro index db1feb0..a447ea9 100644 --- a/Makefile.libretro +++ b/Makefile.libretro @@ -31,7 +31,7 @@ else ifeq ($(platform), osx) SHARED := -dynamiclib else ifeq ($(platform), ios) ARCH := arm - TARGET := $(TARGET_NAME)_libretro.dylib + TARGET := $(TARGET_NAME)_libretro_ios.dylib fpic := -fPIC SHARED := -dynamiclib -- cgit v1.2.3 From 6b5beb44bae19400acddc052b3e475e638f3d50c Mon Sep 17 00:00:00 2001 From: twinaphex Date: Fri, 24 May 2013 00:08:10 +0200 Subject: (NEON ARM) Add NEON ARM core option (Enhanced resolution - slow) --- frontend/libretro.c | 41 ++++++++++++++++++++++++++++++++++++++++- frontend/libretro.h | 9 ++++++++- 2 files changed, 48 insertions(+), 2 deletions(-) diff --git a/frontend/libretro.c b/frontend/libretro.c index 7a7c2ef..8fb58b7 100644 --- a/frontend/libretro.c +++ b/frontend/libretro.c @@ -230,7 +230,22 @@ void out_register_libretro(struct out_driver *drv) } /* libretro */ -void retro_set_environment(retro_environment_t cb) { environ_cb = cb; } +void retro_set_environment(retro_environment_t cb) +{ +#ifdef __ARM_NEON__ + static const struct retro_variable vars[] = { + { "neon_enhancement_enable", "Enhanced resolution (slow); disabled|enabled" }, + { NULL, NULL }, + }; + + environ_cb = cb; + + cb(RETRO_ENVIRONMENT_SET_VARIABLES, (void*)vars); +#else + environ_cb = cb; +#endif +} + void retro_set_video_refresh(retro_video_refresh_t cb) { video_cb = cb; } void retro_set_audio_sample(retro_audio_sample_t cb) { (void)cb; } void retro_set_audio_sample_batch(retro_audio_sample_batch_t cb) { audio_batch_cb = cb; } @@ -710,11 +725,33 @@ static const unsigned short retro_psx_map[] = { }; #define RETRO_PSX_MAP_LEN (sizeof(retro_psx_map) / sizeof(retro_psx_map[0])) +static void update_variables(void) +{ +#ifdef __ARM_NEON__ + struct retro_variable var; + var.value = NULL; + var.key = "neon_enhancement_enable"; + + if (!environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) || !var.value) + return; + + if (strcmp(var.value, "disabled") == 0) + pl_rearmed_cbs.gpu_neon.enhancement_enable = 0; + else if (strcmp(var.value, "enabled") == 0) + pl_rearmed_cbs.gpu_neon.enhancement_enable = 1; +#endif +} + void retro_run(void) { int i; input_poll_cb(); + + bool updated = false; + if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE_UPDATE, &updated) && updated) + update_variables(); + in_keystate = 0; for (i = 0; i < RETRO_PSX_MAP_LEN; i++) if (input_state_cb(1, RETRO_DEVICE_JOYPAD, 0, i)) @@ -795,6 +832,8 @@ void retro_init(void) SaveFuncs.write = save_write; SaveFuncs.seek = save_seek; SaveFuncs.close = save_close; + + update_variables(); } void retro_deinit(void) diff --git a/frontend/libretro.h b/frontend/libretro.h index b02855a..dc5b52b 100755 --- a/frontend/libretro.h +++ b/frontend/libretro.h @@ -452,6 +452,13 @@ enum retro_mod // Result is set to true if some variables are updated by // frontend since last call to RETRO_ENVIRONMENT_GET_VARIABLE. // Variables should be queried with GET_VARIABLE. + // +#define RETRO_ENVIRONMENT_SET_SUPPORT_NO_GAME 18 + // const bool * -- + // If true, the libretro implementation supports calls to retro_load_game() with NULL as argument. + // Used by cores which can run without particular game data. + // This should be called within retro_set_environment() only. + // Pass this to retro_video_refresh_t if rendering to hardware. // Passing NULL to retro_video_refresh_t is still a frame dupe as normal. @@ -496,7 +503,7 @@ typedef void (*retro_keyboard_event_t)(bool down, unsigned keycode, uint32_t cha struct retro_keyboard_callback { - retro_keyboard_event_t callback; + retro_keyboard_event_t callback; }; // Callbacks for RETRO_ENVIRONMENT_SET_DISK_CONTROL_INTERFACE. -- cgit v1.2.3 From a8f3f1d2071185633a8ccaa387e8d3c68fba5014 Mon Sep 17 00:00:00 2001 From: twinaphex Date: Fri, 24 May 2013 01:19:56 +0200 Subject: (Libretro) Add core options - Frameskip and (for ARM NEON only) Software filter (None/Scale2x/Eagle2x) --- frontend/libretro.c | 45 +++++++++++++++++++++++++++++++++------------ 1 file changed, 33 insertions(+), 12 deletions(-) diff --git a/frontend/libretro.c b/frontend/libretro.c index 8fb58b7..f212cdd 100644 --- a/frontend/libretro.c +++ b/frontend/libretro.c @@ -39,6 +39,8 @@ static int samples_sent, samples_to_send; static int plugins_opened; static int is_pal_mode; +extern int soft_filter; + /* memory card data */ extern char Mcd1Data[MCD_SIZE]; extern char McdDisable[2]; @@ -232,18 +234,18 @@ void out_register_libretro(struct out_driver *drv) /* libretro */ void retro_set_environment(retro_environment_t cb) { -#ifdef __ARM_NEON__ static const struct retro_variable vars[] = { + { "frameskip", "Frameskip; 0|1|2|3" }, +#ifdef __ARM_NEON__ + { "soft_filter", "Software filter; none|scale2x|eagle2x" }, { "neon_enhancement_enable", "Enhanced resolution (slow); disabled|enabled" }, +#endif { NULL, NULL }, }; environ_cb = cb; cb(RETRO_ENVIRONMENT_SET_VARIABLES, (void*)vars); -#else - environ_cb = cb; -#endif } void retro_set_video_refresh(retro_video_refresh_t cb) { video_cb = cb; } @@ -727,18 +729,37 @@ static const unsigned short retro_psx_map[] = { static void update_variables(void) { -#ifdef __ARM_NEON__ struct retro_variable var; + var.value = NULL; - var.key = "neon_enhancement_enable"; + var.key = "frameskip"; - if (!environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) || !var.value) - return; + if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) || var.value) + pl_rearmed_cbs.frameskip = atoi(var.value); +#ifdef __ARM_NEON__ + var.value = NULL; + var.key = "soft_filter"; - if (strcmp(var.value, "disabled") == 0) - pl_rearmed_cbs.gpu_neon.enhancement_enable = 0; - else if (strcmp(var.value, "enabled") == 0) - pl_rearmed_cbs.gpu_neon.enhancement_enable = 1; + if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) || var.value) + { + if (strcmp(var.value, "none")) + soft_filter = 0; + else if (strcmp(var.value, "scale2x")) + soft_filter = 1; + else if (strcmp(var.value, "eagle2x")) + soft_filter = 2; + } + + var.value = NULL; + var.key = "neon_enhancement_enable"; + + if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) || var.value) + { + if (strcmp(var.value, "disabled") == 0) + pl_rearmed_cbs.gpu_neon.enhancement_enable = 0; + else if (strcmp(var.value, "enabled") == 0) + pl_rearmed_cbs.gpu_neon.enhancement_enable = 1; + } #endif } -- cgit v1.2.3 From 4fcb9a11c1f3d13d263bff7d39396a4c776b7e6b Mon Sep 17 00:00:00 2001 From: twinaphex Date: Fri, 24 May 2013 01:28:43 +0200 Subject: Take out soft_filter for now as core option --- frontend/libretro.c | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/frontend/libretro.c b/frontend/libretro.c index f212cdd..53e7fa5 100644 --- a/frontend/libretro.c +++ b/frontend/libretro.c @@ -39,8 +39,6 @@ static int samples_sent, samples_to_send; static int plugins_opened; static int is_pal_mode; -extern int soft_filter; - /* memory card data */ extern char Mcd1Data[MCD_SIZE]; extern char McdDisable[2]; @@ -237,7 +235,6 @@ void retro_set_environment(retro_environment_t cb) static const struct retro_variable vars[] = { { "frameskip", "Frameskip; 0|1|2|3" }, #ifdef __ARM_NEON__ - { "soft_filter", "Software filter; none|scale2x|eagle2x" }, { "neon_enhancement_enable", "Enhanced resolution (slow); disabled|enabled" }, #endif { NULL, NULL }, @@ -737,19 +734,6 @@ static void update_variables(void) if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) || var.value) pl_rearmed_cbs.frameskip = atoi(var.value); #ifdef __ARM_NEON__ - var.value = NULL; - var.key = "soft_filter"; - - if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) || var.value) - { - if (strcmp(var.value, "none")) - soft_filter = 0; - else if (strcmp(var.value, "scale2x")) - soft_filter = 1; - else if (strcmp(var.value, "eagle2x")) - soft_filter = 2; - } - var.value = NULL; var.key = "neon_enhancement_enable"; -- cgit v1.2.3 From 2c67e0e80f01116f7ce95cbe7161a9c331516fe2 Mon Sep 17 00:00:00 2001 From: twinaphex Date: Fri, 24 May 2013 03:13:24 +0200 Subject: (Libretro) Add NEON interlace enable core option and region core option --- frontend/libretro.c | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/frontend/libretro.c b/frontend/libretro.c index 53e7fa5..8b67f17 100644 --- a/frontend/libretro.c +++ b/frontend/libretro.c @@ -234,7 +234,9 @@ void retro_set_environment(retro_environment_t cb) { static const struct retro_variable vars[] = { { "frameskip", "Frameskip; 0|1|2|3" }, + { "region", "Region; Auto|NTSC|PAL" }, #ifdef __ARM_NEON__ + { "neon_interlace_enable", "Enable interlacing mode(s); disabled|enabled" }, { "neon_enhancement_enable", "Enhanced resolution (slow); disabled|enabled" }, #endif { NULL, NULL }, @@ -733,7 +735,33 @@ static void update_variables(void) if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) || var.value) pl_rearmed_cbs.frameskip = atoi(var.value); + + var.value = NULL; + var.key = "region"; + + if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) || var.value) + { + Config.PsxAuto = 0; + if (strcmp(var.value, "Automatic") == 0) + Config.PsxAuto = 1; + else if (strcmp(var.value, "NTSC") == 0) + Config.PsxType = 0; + else if (strcmp(var.value, "PAL") == 0) + Config.PsxType = 1; + } #ifdef __ARM_NEON__ + var.value = "NULL"; + var.key = "neon_interlace_enable"; + + if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) || var.value) + { + if (strcmp(var.value, "disabled") == 0) + pl_rearmed_cbs.gpu_neon.allow_interlace = 0; + else if (strcmp(var.value, "enabled") == 0) + pl_rearmed_cbs.gpu_neon.allow_interlace = 1; + } + + var.value = NULL; var.key = "neon_enhancement_enable"; -- cgit v1.2.3 From 6790d7fdb483f965f5054b94d3508eaee1c63b3e Mon Sep 17 00:00:00 2001 From: twinaphex Date: Fri, 24 May 2013 13:41:26 +0200 Subject: Comment out neon_enhancement_enable for now --- frontend/libretro.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/frontend/libretro.c b/frontend/libretro.c index 8b67f17..16feeec 100644 --- a/frontend/libretro.c +++ b/frontend/libretro.c @@ -237,7 +237,9 @@ void retro_set_environment(retro_environment_t cb) { "region", "Region; Auto|NTSC|PAL" }, #ifdef __ARM_NEON__ { "neon_interlace_enable", "Enable interlacing mode(s); disabled|enabled" }, +#if 0 { "neon_enhancement_enable", "Enhanced resolution (slow); disabled|enabled" }, +#endif #endif { NULL, NULL }, }; @@ -761,7 +763,7 @@ static void update_variables(void) pl_rearmed_cbs.gpu_neon.allow_interlace = 1; } - +#if 0 var.value = NULL; var.key = "neon_enhancement_enable"; @@ -773,6 +775,7 @@ static void update_variables(void) pl_rearmed_cbs.gpu_neon.enhancement_enable = 1; } #endif +#endif } void retro_run(void) -- cgit v1.2.3 From c8a9b436fca00b2facf28dd3098ea09e3a732709 Mon Sep 17 00:00:00 2001 From: twinaphex Date: Sat, 25 May 2013 23:00:18 +0200 Subject: Add system message warning if a BIOS file could not be found --- frontend/libretro.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/frontend/libretro.c b/frontend/libretro.c index 16feeec..024ea7a 100644 --- a/frontend/libretro.c +++ b/frontend/libretro.c @@ -842,7 +842,11 @@ void retro_init(void) fclose(f); } else + { SysPrintf("no BIOS files found.\n"); + const char *str = "no BIOS found, expect bugs!"; + environ_cb(RETRO_ENVIRONMENT_SET_MESSAGE, (void*)&str); + } level = 1; environ_cb(RETRO_ENVIRONMENT_SET_PERFORMANCE_LEVEL, &level); -- cgit v1.2.3 From 0133074b6007a703ad76b02e2a6fcea97a005647 Mon Sep 17 00:00:00 2001 From: twinaphex Date: Sat, 25 May 2013 23:11:31 +0200 Subject: Pass correct type for RETRO_ENVIRONMENT_SET_MESSAGE --- frontend/libretro.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/frontend/libretro.c b/frontend/libretro.c index 024ea7a..62f968a 100644 --- a/frontend/libretro.c +++ b/frontend/libretro.c @@ -844,8 +844,12 @@ void retro_init(void) else { SysPrintf("no BIOS files found.\n"); - const char *str = "no BIOS found, expect bugs!"; - environ_cb(RETRO_ENVIRONMENT_SET_MESSAGE, (void*)&str); + struct retro_message msg = + { + "no BIOS found, expect bugs!", + 180 + }; + environ_cb(RETRO_ENVIRONMENT_SET_MESSAGE, (void*)&msg); } level = 1; -- cgit v1.2.3 From 24aeb31fad7b983a60ef448cba97d9a2f167664d Mon Sep 17 00:00:00 2001 From: twinaphex Date: Sun, 26 May 2013 19:00:45 +0200 Subject: Revert "Add hack for broken bin/cue loading right now at startup" This reverts commit 5f8aa603b1f68d4bf4dbd341fed0e31b21f11bde. --- Makefile.libretro | 2 -- libpcsxcore/cdriso.c | 2 -- 2 files changed, 4 deletions(-) diff --git a/Makefile.libretro b/Makefile.libretro index a447ea9..9436c8a 100644 --- a/Makefile.libretro +++ b/Makefile.libretro @@ -108,8 +108,6 @@ else CFLAGS += -D__WIN32__ -D__WIN32_LIBRETRO__ endif -CFLAGS += -D__LIBRETRO__ - CFLAGS += -fPIC ifneq ($(platform),qnx) LDLIBS += -lpthread diff --git a/libpcsxcore/cdriso.c b/libpcsxcore/cdriso.c index 24ac891..9ca4172 100644 --- a/libpcsxcore/cdriso.c +++ b/libpcsxcore/cdriso.c @@ -327,7 +327,6 @@ static int parsetoc(const char *isofile) { return -1; } } -#ifndef __LIBRETRO__ // check if it's really a TOC named as a .cue fgets(linebuf, sizeof(linebuf), fi); token = strtok(tmp, " "); @@ -336,7 +335,6 @@ static int parsetoc(const char *isofile) { return -1; } fseek(fi, 0, SEEK_SET); -#endif } memset(&ti, 0, sizeof(ti)); -- cgit v1.2.3 From 268c669a9bccc1b5ebf0ebd169b540642406d142 Mon Sep 17 00:00:00 2001 From: twinaphex Date: Sun, 26 May 2013 22:44:23 +0200 Subject: Remove #if 0 around NEON enhancement --- frontend/libretro.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/frontend/libretro.c b/frontend/libretro.c index 1e9929d..ed76798 100644 --- a/frontend/libretro.c +++ b/frontend/libretro.c @@ -243,9 +243,7 @@ void retro_set_environment(retro_environment_t cb) { "region", "Region; Auto|NTSC|PAL" }, #ifdef __ARM_NEON__ { "neon_interlace_enable", "Enable interlacing mode(s); disabled|enabled" }, -#if 0 { "neon_enhancement_enable", "Enhanced resolution (slow); disabled|enabled" }, -#endif #endif { NULL, NULL }, }; @@ -769,7 +767,6 @@ static void update_variables(bool in_flight) pl_rearmed_cbs.gpu_neon.allow_interlace = 1; } -#if 0 var.value = NULL; var.key = "neon_enhancement_enable"; @@ -780,7 +777,6 @@ static void update_variables(bool in_flight) else if (strcmp(var.value, "enabled") == 0) pl_rearmed_cbs.gpu_neon.enhancement_enable = 1; } -#endif #endif if (in_flight) { -- cgit v1.2.3 From 4e613fda6acf04836881621d40717e1df168c9e2 Mon Sep 17 00:00:00 2001 From: twinaphex Date: Mon, 27 May 2013 00:31:25 +0200 Subject: Core option: Add neon_enhancement_no_main --- frontend/libretro.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/frontend/libretro.c b/frontend/libretro.c index 413098d..9be52f5 100644 --- a/frontend/libretro.c +++ b/frontend/libretro.c @@ -244,6 +244,7 @@ void retro_set_environment(retro_environment_t cb) #ifdef __ARM_NEON__ { "neon_interlace_enable", "Enable interlacing mode(s); disabled|enabled" }, { "neon_enhancement_enable", "Enhanced resolution (slow); disabled|enabled" }, + { "neon_enhancement_no_main", "Enhanced resolution speed hack; disabled|enabled" }, #endif { NULL, NULL }, }; @@ -778,6 +779,17 @@ static void update_variables(bool in_flight) else if (strcmp(var.value, "enabled") == 0) pl_rearmed_cbs.gpu_neon.enhancement_enable = 1; } + + var.value = NULL; + var.key = "neon_enhancement_no_main"; + + if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) || var.value) + { + if (strcmp(var.value, "disabled") == 0) + pl_rearmed_cbs.gpu_neon.enhancement_no_main = 0; + else if (strcmp(var.value, "enabled") == 0) + pl_rearmed_cbs.gpu_neon.enhancement_no_main = 1; + } #endif if (in_flight) { -- cgit v1.2.3 From 9b56b10a186877d32c47be051250ffb307404e78 Mon Sep 17 00:00:00 2001 From: twinaphex Date: Mon, 27 May 2013 12:28:34 +0200 Subject: (Blackberry Playbook) Fix Blackberry Playbook build - strcasestr is not implemented --- frontend/libretro.c | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/frontend/libretro.c b/frontend/libretro.c index 9be52f5..ec034c2 100644 --- a/frontend/libretro.c +++ b/frontend/libretro.c @@ -591,6 +591,33 @@ static void extract_directory(char *buf, const char *path, size_t size) } } +#ifdef __QNX__ +/* Blackberry QNX doesn't have strcasestr */ + +/* + * Find the first occurrence of find in s, ignore case. + */ +char * +strcasestr(const char *s, const char*find) +{ + char c, sc; + size_t len; + + if ((c = *find++) != 0) { + c = tolower((unsigned char)c); + len = strlen(find); + do { + do { + if ((sc = *s++) == 0) + return (NULL); + } while ((char)tolower((unsigned char)sc) != c); + } while (strncasecmp(s, find, len) != 0); + s--; + } + return ((char *)s); +} +#endif + bool retro_load_game(const struct retro_game_info *info) { size_t i; -- cgit v1.2.3 From e88aeb509e02e532a2972acdf5acd84d33611eb2 Mon Sep 17 00:00:00 2001 From: meancoot Date: Tue, 18 Jun 2013 22:46:43 -0400 Subject: libretro: Add analog option for player 1 --- frontend/libretro.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/frontend/libretro.c b/frontend/libretro.c index 103ee8e..be132a1 100644 --- a/frontend/libretro.c +++ b/frontend/libretro.c @@ -242,6 +242,7 @@ void retro_set_environment(retro_environment_t cb) static const struct retro_variable vars[] = { { "frameskip", "Frameskip; 0|1|2|3" }, { "region", "Region; Auto|NTSC|PAL" }, + { "pad1type", "Pad 1 Type; standard|analog" }, #ifdef __ARM_NEON__ { "neon_interlace_enable", "Enable interlacing mode(s); disabled|enabled" }, { "neon_enhancement_enable", "Enhanced resolution (slow); disabled|enabled" }, @@ -785,6 +786,17 @@ static void update_variables(bool in_flight) else if (strcmp(var.value, "PAL") == 0) Config.PsxType = 1; } + + var.value = NULL; + var.key = "pad1type"; + + if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) || var.value) + { + in_type1 = PSE_PAD_TYPE_STANDARD; + if (strcmp(var.value, "analog") == 0) + in_type1 = PSE_PAD_TYPE_ANALOGPAD; + } + #ifdef __ARM_NEON__ var.value = "NULL"; var.key = "neon_interlace_enable"; @@ -852,6 +864,14 @@ void retro_run(void) if (input_state_cb(0, RETRO_DEVICE_JOYPAD, 0, i)) in_keystate |= retro_psx_map[i]; + if (in_type1 == PSE_PAD_TYPE_ANALOGPAD) + { + in_a1[0] = (input_state_cb(0, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_LEFT, RETRO_DEVICE_ID_ANALOG_X) / 256) + 128; + in_a1[1] = (input_state_cb(0, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_LEFT, RETRO_DEVICE_ID_ANALOG_Y) / 256) + 128; + in_a2[0] = (input_state_cb(0, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_RIGHT, RETRO_DEVICE_ID_ANALOG_X) / 256) + 128; + in_a2[1] = (input_state_cb(0, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_RIGHT, RETRO_DEVICE_ID_ANALOG_Y) / 256) + 128; + } + stop = 0; psxCpu->Execute(); -- cgit v1.2.3 From 5d0bfd318877166df186565fb9a2a940c241a43f Mon Sep 17 00:00:00 2001 From: twinaphex Date: Sat, 13 Jul 2013 18:44:43 +0200 Subject: (Makefile libretro) Make more generic ARM target --- Makefile.libretro | 28 +++++++++++++++++++++++----- 1 file changed, 23 insertions(+), 5 deletions(-) diff --git a/Makefile.libretro b/Makefile.libretro index 9436c8a..450860d 100644 --- a/Makefile.libretro +++ b/Makefile.libretro @@ -90,15 +90,33 @@ else ifeq ($(platform), qnx) ARCH = arm CFLAGS += -DBASE_ADDR_FIXED=0 -D__BLACKBERRY_QNX__ -marm -mcpu=cortex-a9 -mtune=cortex-a9 -mfpu=neon -mfloat-abi=softfp ASFLAGS += -mcpu=cortex-a9 -mfpu=neon -mfloat-abi=softfp -else ifeq ($(platform), arm) +else ifneq (,$(findstring armv,$(platform))) TARGET := $(TARGET_NAME)_libretro.so - HAVE_NEON = 1 - USE_DYNAREC = 1 + SHARED := -shared -Wl,--no-undefined DRC_CACHE_BASE = 0 +ifneq (,$(findstring cortexa8,$(platform))) + CFLAGS += -marm -mcpu=cortex-a8 + ASFLAGS += -mcpu=cortex-a8 +else ifneq (,$(findstring cortexa9,$(platform))) + CFLAGS += -marm -mcpu=cortex-a9 + ASFLAGS += -mcpu=cortex-a9 +endif + CFLAGS += -marm +ifneq (,$(findstring neon,$(platform))) + CFLAGS += -mfpu=neon + ASFLAGS += -mfpu=neon + HAVE_NEON = 1 BUILTIN_GPU = neon +endif +ifneq (,$(findstring softfloat,$(platform))) + CFLAGS += -mfloat-abi=softfp + ASFLAGS += -mfloat-abi=softfp +else ifneq (,$(findstring hardfloat,$(platform))) + CFLAGS += -mfloat-abi=hard + ASFLAGS += -mfloat-abi=hard +endif ARCH = arm - CFLAGS += -marm -mcpu=cortex-a8 -mfpu=neon - ASFLAGS += -mcpu=cortex-a8 -mfpu=neon + USE_DYNAREC = 1 else TARGET := $(TARGET_NAME)_retro.dll CC = gcc -- cgit v1.2.3 From 175daa57787ba7924afc61645ee6ddb6517c5641 Mon Sep 17 00:00:00 2001 From: twinaphex Date: Sat, 30 Nov 2013 02:30:36 +0100 Subject: (iOS) Add min SDK version --- Makefile.libretro | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Makefile.libretro b/Makefile.libretro index 450860d..73faa5c 100644 --- a/Makefile.libretro +++ b/Makefile.libretro @@ -35,15 +35,15 @@ ARCH := arm fpic := -fPIC SHARED := -dynamiclib - CC = clang -arch armv7 -isysroot $(IOSSDK) - CXX = clang++ -arch armv7 -isysroot $(IOSSDK) - CC_AS = perl ./tools/gas-preprocessor.pl $(CC) - CFLAGS += -mcpu=cortex-a8 -mtune=cortex-a8 -mfpu=neon -marm + CC = clang -arch armv7 -isysroot $(IOSSDK) -miphone-version-min=5.0 + CXX = clang++ -arch armv7 -isysroot $(IOSSDK) -miphone-version-min=5.0 + CC_AS = perl ./tools/gas-preprocessor.pl $(CC) -miphone-version-min=5.0 + CFLAGS += -mcpu=cortex-a8 -mtune=cortex-a8 -mfpu=neon -marm -miphone-version-min=5.0 ASFLAGS += -mcpu=cortex-a8 -mtune=cortex-a8 -mfpu=neon HAVE_NEON = 1 BUILTIN_GPU = neon USE_DYNAREC = 1 - CFLAGS += -DIOS + CFLAGS += -DIOS -miphoneos-version-min=5.0 else ifeq ($(platform), ps3) TARGET := $(TARGET_NAME)_libretro_ps3.a CC = $(CELL_SDK)/host-win32/ppu/bin/ppu-lv2-gcc.exe -- cgit v1.2.3 From 9da55cadc9fba30015ed7333aa10c100a8d8bfdd Mon Sep 17 00:00:00 2001 From: twinaphex Date: Mon, 2 Dec 2013 23:58:23 +0100 Subject: (iOS) Add min SDK version for compatbility --- Makefile.libretro | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Makefile.libretro b/Makefile.libretro index 73faa5c..6f7b29a 100644 --- a/Makefile.libretro +++ b/Makefile.libretro @@ -35,10 +35,10 @@ ARCH := arm fpic := -fPIC SHARED := -dynamiclib - CC = clang -arch armv7 -isysroot $(IOSSDK) -miphone-version-min=5.0 - CXX = clang++ -arch armv7 -isysroot $(IOSSDK) -miphone-version-min=5.0 - CC_AS = perl ./tools/gas-preprocessor.pl $(CC) -miphone-version-min=5.0 - CFLAGS += -mcpu=cortex-a8 -mtune=cortex-a8 -mfpu=neon -marm -miphone-version-min=5.0 + CC = clang -arch armv7 -isysroot $(IOSSDK) -miphoneos-version-min=5.0 + CXX = clang++ -arch armv7 -isysroot $(IOSSDK) -miphoneos-version-min=5.0 + CC_AS = perl ./tools/gas-preprocessor.pl $(CC) -miphoneos-version-min=5.0 + CFLAGS += -mcpu=cortex-a8 -mtune=cortex-a8 -mfpu=neon -marm -miphoneos-version-min=5.0 ASFLAGS += -mcpu=cortex-a8 -mtune=cortex-a8 -mfpu=neon HAVE_NEON = 1 BUILTIN_GPU = neon -- cgit v1.2.3 From 779692e400119ccb41a879d80fbd3e3ad71b4591 Mon Sep 17 00:00:00 2001 From: twinaphex Date: Wed, 18 Dec 2013 20:41:08 +0100 Subject: Update libretro.h --- frontend/libretro.h | 363 +++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 356 insertions(+), 7 deletions(-) diff --git a/frontend/libretro.h b/frontend/libretro.h index dc5b52b..ede60f0 100755 --- a/frontend/libretro.h +++ b/frontend/libretro.h @@ -1,3 +1,25 @@ +/* Copyright (C) 2010-2013 The RetroArch team + * + * --------------------------------------------------------------------------------------- + * The following license statement only applies to this libretro API header (libretro.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. + */ + #ifndef LIBRETRO_H__ #define LIBRETRO_H__ @@ -72,6 +94,9 @@ extern "C" { // Eventually _PRESSED will return false for an index. No further presses are registered at this point. #define RETRO_DEVICE_POINTER 6 +// FIXME: Document this. +#define RETRO_DEVICE_SENSOR_ACCELEROMETER 7 + // These device types are specializations of the base types above. // They should only be used in retro_set_controller_type() to inform libretro implementations // about use of a very specific device type. @@ -128,6 +153,11 @@ extern "C" { #define RETRO_DEVICE_ID_POINTER_Y 1 #define RETRO_DEVICE_ID_POINTER_PRESSED 2 +// Id values for SENSOR types. +#define RETRO_DEVICE_ID_SENSOR_ACCELEROMETER_X 0 +#define RETRO_DEVICE_ID_SENSOR_ACCELEROMETER_Y 1 +#define RETRO_DEVICE_ID_SENSOR_ACCELEROMETER_Z 2 + // Returned from retro_get_region(). #define RETRO_REGION_NTSC 0 #define RETRO_REGION_PAL 1 @@ -335,6 +365,8 @@ enum retro_mod // If set, this call is not part of the public libretro API yet. It can change or be removed at any time. #define RETRO_ENVIRONMENT_EXPERIMENTAL 0x10000 +// Environment callback to be used internally in frontend. +#define RETRO_ENVIRONMENT_PRIVATE 0x20000 // Environment commands. #define RETRO_ENVIRONMENT_SET_ROTATION 1 // const unsigned * -- @@ -412,10 +444,8 @@ enum retro_mod // Sets an interface which frontend can use to eject and insert disk images. // This is used for games which consist of multiple images and must be manually // swapped out by the user (e.g. PSX). -#define RETRO_ENVIRONMENT_SET_HW_RENDER (14 | RETRO_ENVIRONMENT_EXPERIMENTAL) +#define RETRO_ENVIRONMENT_SET_HW_RENDER 14 // struct retro_hw_render_callback * -- - // NOTE: This call is currently very experimental, and should not be considered part of the public API. - // The interface could be changed or removed at any time. // Sets an interface to let a libretro core render with hardware acceleration. // Should be called in retro_load_game(). // If successful, libretro cores will be able to render to a frontend-provided framebuffer. @@ -423,7 +453,7 @@ enum retro_mod // If HW rendering is used, pass only RETRO_HW_FRAME_BUFFER_VALID or NULL to retro_video_refresh_t. #define RETRO_ENVIRONMENT_GET_VARIABLE 15 // struct retro_variable * -- - // Interface to aquire user-defined information from environment + // Interface to acquire user-defined information from environment // that cannot feasibly be supported in a multi-system way. // 'key' should be set to a key which has already been set by SET_VARIABLES. // 'data' will be set to a value or NULL. @@ -458,13 +488,312 @@ enum retro_mod // If true, the libretro implementation supports calls to retro_load_game() with NULL as argument. // Used by cores which can run without particular game data. // This should be called within retro_set_environment() only. - + // +#define RETRO_ENVIRONMENT_GET_LIBRETRO_PATH 19 + // const char ** -- + // Retrieves the absolute path from where this libretro implementation was loaded. + // NULL is returned if the libretro was loaded statically (i.e. linked statically to frontend), or if the path cannot be determined. + // Mostly useful in cooperation with SET_SUPPORT_NO_GAME as assets can be loaded without ugly hacks. + // + // +// Environment 20 was an obsolete version of SET_AUDIO_CALLBACK. It was not used by any known core at the time, +// and was removed from the API. +#define RETRO_ENVIRONMENT_SET_AUDIO_CALLBACK 22 + // const struct retro_audio_callback * -- + // Sets an interface which is used to notify a libretro core about audio being available for writing. + // The callback can be called from any thread, so a core using this must have a thread safe audio implementation. + // It is intended for games where audio and video are completely asynchronous and audio can be generated on the fly. + // This interface is not recommended for use with emulators which have highly synchronous audio. + // + // The callback only notifies about writability; the libretro core still has to call the normal audio callbacks + // to write audio. The audio callbacks must be called from within the notification callback. + // The amount of audio data to write is up to the implementation. + // Generally, the audio callback will be called continously in a loop. + // + // Due to thread safety guarantees and lack of sync between audio and video, a frontend + // can selectively disallow this interface based on internal configuration. A core using + // this interface must also implement the "normal" audio interface. + // + // A libretro core using SET_AUDIO_CALLBACK should also make use of SET_FRAME_TIME_CALLBACK. +#define RETRO_ENVIRONMENT_SET_FRAME_TIME_CALLBACK 21 + // const struct retro_frame_time_callback * -- + // Lets the core know how much time has passed since last invocation of retro_run(). + // The frontend can tamper with the timing to fake fast-forward, slow-motion, frame stepping, etc. + // In this case the delta time will use the reference value in frame_time_callback.. + // +#define RETRO_ENVIRONMENT_GET_RUMBLE_INTERFACE 23 + // struct retro_rumble_interface * -- + // Gets an interface which is used by a libretro core to set state of rumble motors in controllers. + // A strong and weak motor is supported, and they can be controlled indepedently. + // +#define RETRO_ENVIRONMENT_GET_INPUT_DEVICE_CAPABILITIES 24 + // uint64_t * -- + // Gets a bitmask telling which device type are expected to be handled properly in a call to retro_input_state_t. + // Devices which are not handled or recognized always return 0 in retro_input_state_t. + // Example bitmask: caps = (1 << RETRO_DEVICE_JOYPAD) | (1 << RETRO_DEVICE_ANALOG). + // Should only be called in retro_run(). + // +#define RETRO_ENVIRONMENT_GET_SENSOR_INTERFACE (25 | RETRO_ENVIRONMENT_EXPERIMENTAL) + // struct retro_sensor_interface * -- + // Gets access to the sensor interface. + // The purpose of this interface is to allow + // setting state related to sensors such as polling rate, enabling/disable it entirely, etc. + // Reading sensor state is done via the normal input_state_callback API. + // +#define RETRO_ENVIRONMENT_GET_CAMERA_INTERFACE (26 | RETRO_ENVIRONMENT_EXPERIMENTAL) + // struct retro_camera_callback * -- + // Gets an interface to a video camera driver. + // A libretro core can use this interface to get access to a video camera. + // New video frames are delivered in a callback in same thread as retro_run(). + // + // GET_CAMERA_INTERFACE should be called in retro_load_game(). + // + // Depending on the camera implementation used, camera frames will be delivered as a raw framebuffer, + // or as an OpenGL texture directly. + // + // The core has to tell the frontend here which types of buffers can be handled properly. + // An OpenGL texture can only be handled when using a libretro GL core (SET_HW_RENDER). + // It is recommended to use a libretro GL core when using camera interface. + // + // The camera is not started automatically. The retrieved start/stop functions must be used to explicitly + // start and stop the camera driver. + // +#define RETRO_ENVIRONMENT_GET_LOG_INTERFACE 27 + // struct retro_log_callback * -- + // Gets an interface for logging. This is useful for logging in a cross-platform way + // as certain platforms cannot use use stderr for logging. It also allows the frontend to + // show logging information in a more suitable way. + // If this interface is not used, libretro cores should log to stderr as desired. +#define RETRO_ENVIRONMENT_GET_PERF_INTERFACE 28 + // struct retro_perf_callback * -- + // Gets an interface for performance counters. This is useful for performance logging in a + // cross-platform way and for detecting architecture-specific features, such as SIMD support. + +enum retro_log_level +{ + RETRO_LOG_DEBUG = 0, + RETRO_LOG_INFO, + RETRO_LOG_WARN, + RETRO_LOG_ERROR, + + RETRO_LOG_DUMMY = INT_MAX +}; + +// Logging function. Takes log level argument as well. +typedef void (*retro_log_printf_t)(enum retro_log_level level, const char *fmt, ...); + +struct retro_log_callback +{ + retro_log_printf_t log; +}; + +// Performance related functions +// +// ID values for SIMD CPU features +#define RETRO_SIMD_SSE (1 << 0) +#define RETRO_SIMD_SSE2 (1 << 1) +#define RETRO_SIMD_VMX (1 << 2) +#define RETRO_SIMD_VMX128 (1 << 3) +#define RETRO_SIMD_AVX (1 << 4) +#define RETRO_SIMD_NEON (1 << 5) +#define RETRO_SIMD_SSE3 (1 << 6) +#define RETRO_SIMD_SSSE3 (1 << 7) + +typedef uint64_t retro_perf_tick_t; +typedef int64_t retro_time_t; + +struct retro_perf_counter +{ + const char *ident; + retro_perf_tick_t start; + retro_perf_tick_t total; + retro_perf_tick_t call_cnt; + + bool registered; +}; + +// Returns current time in microseconds. Tries to use the most accurate timer available. +typedef retro_time_t (*retro_perf_get_time_usec_t)(void); +// A simple counter. Usually nanoseconds, but can also be CPU cycles. +// Can be used directly if desired (when creating a more sophisticated performance counter system). +typedef retro_perf_tick_t (*retro_perf_get_counter_t)(void); +// Returns a bit-mask of detected CPU features (RETRO_SIMD_*). +typedef uint64_t (*retro_get_cpu_features_t)(void); +// Asks frontend to log and/or display the state of performance counters. +// Performance counters can always be poked into manually as well. +typedef void (*retro_perf_log_t)(void); +// Register a performance counter. +// ident field must be set with a discrete value and other values in retro_perf_counter must be 0. +// Registering can be called multiple times. To avoid calling to frontend redundantly, you can check registered field first. +typedef void (*retro_perf_register_t)(struct retro_perf_counter *counter); +// Starts and stops a registered counter. +typedef void (*retro_perf_start_t)(struct retro_perf_counter *counter); +typedef void (*retro_perf_stop_t)(struct retro_perf_counter *counter); + +// For convenience it can be useful to wrap register, start and stop in macros. +// E.g.: +// #ifdef LOG_PERFORMANCE +// #define RETRO_PERFORMANCE_INIT(perf_cb, name) static struct retro_perf_counter name = {#name}; if (!name.registered) perf_cb.perf_register(&(name)) +// #define RETRO_PERFORMANCE_START(perf_cb, name) perf_cb.perf_start(&(name)) +// #define RETRO_PERFORMANCE_STOP(perf_cb, name) perf_cb.perf_stop(&(name)) +// #else +// ... Blank macros ... +// #endif +// These can then be used mid-functions around code snippets. +// +// extern struct retro_perf_callback perf_cb; // Somewhere in the core. +// +// void do_some_heavy_work(void) +// { +// RETRO_PERFORMANCE_INIT(cb, work_1); +// RETRO_PERFORMANCE_START(cb, work_1); +// heavy_work_1(); +// RETRO_PERFORMANCE_STOP(cb, work_1); +// +// RETRO_PERFORMANCE_INIT(cb, work_2); +// RETRO_PERFORMANCE_START(cb, work_2); +// heavy_work_2(); +// RETRO_PERFORMANCE_STOP(cb, work_2); +// } +// +// void retro_deinit(void) +// { +// perf_cb.perf_log(); // Log all perf counters here for example. +// } + +struct retro_perf_callback +{ + retro_perf_get_time_usec_t get_time_usec; + retro_get_cpu_features_t get_cpu_features; + + retro_perf_get_counter_t get_perf_counter; + retro_perf_register_t perf_register; + retro_perf_start_t perf_start; + retro_perf_stop_t perf_stop; + retro_perf_log_t perf_log; +}; + +// FIXME: Document the sensor API and work out behavior. +// It will be marked as experimental until then. +enum retro_sensor_action +{ + RETRO_SENSOR_ACCELEROMETER_ENABLE = 0, + RETRO_SENSOR_ACCELEROMETER_DISABLE, + + RETRO_SENSOR_DUMMY = INT_MAX +}; + +typedef bool (*retro_set_sensor_state_t)(unsigned port, enum retro_sensor_action action, unsigned rate); +struct retro_sensor_interface +{ + retro_set_sensor_state_t set_sensor_state; +}; +//// + +enum retro_camera_buffer +{ + RETRO_CAMERA_BUFFER_OPENGL_TEXTURE = 0, + RETRO_CAMERA_BUFFER_RAW_FRAMEBUFFER, + + RETRO_CAMERA_BUFFER_DUMMY = INT_MAX +}; + +// Starts the camera driver. Can only be called in retro_run(). +typedef bool (*retro_camera_start_t)(void); +// Stops the camera driver. Can only be called in retro_run(). +typedef void (*retro_camera_stop_t)(void); +// Callback which signals when the camera driver is initialized and/or deinitialized. +// retro_camera_start_t can be called in initialized callback. +typedef void (*retro_camera_lifetime_status_t)(void); +// A callback for raw framebuffer data. buffer points to an XRGB8888 buffer. +// Width, height and pitch are similar to retro_video_refresh_t. +// First pixel is top-left origin. +typedef void (*retro_camera_frame_raw_framebuffer_t)(const uint32_t *buffer, unsigned width, unsigned height, size_t pitch); +// A callback for when OpenGL textures are used. +// +// texture_id is a texture owned by camera driver. +// Its state or content should be considered immutable, except for things like texture filtering and clamping. +// +// texture_target is the texture target for the GL texture. +// These can include e.g. GL_TEXTURE_2D, GL_TEXTURE_RECTANGLE, and possibly more depending on extensions. +// +// affine points to a packed 3x3 column-major matrix used to apply an affine transform to texture coordinates. (affine_matrix * vec3(coord_x, coord_y, 1.0)) +// After transform, normalized texture coord (0, 0) should be bottom-left and (1, 1) should be top-right (or (width, height) for RECTANGLE). +// +// GL-specific typedefs are avoided here to avoid relying on gl.h in the API definition. +typedef void (*retro_camera_frame_opengl_texture_t)(unsigned texture_id, unsigned texture_target, const float *affine); +struct retro_camera_callback +{ + uint64_t caps; // Set by libretro core. Example bitmask: caps = (1 << RETRO_CAMERA_BUFFER_OPENGL_TEXTURE) | (1 << RETRO_CAMERA_BUFFER_RAW_FRAMEBUFFER). + + unsigned width; // Desired resolution for camera. Is only used as a hint. + unsigned height; + retro_camera_start_t start; // Set by frontend. + retro_camera_stop_t stop; // Set by frontend. + + retro_camera_frame_raw_framebuffer_t frame_raw_framebuffer; // Set by libretro core if raw framebuffer callbacks will be used. + retro_camera_frame_opengl_texture_t frame_opengl_texture; // Set by libretro core if OpenGL texture callbacks will be used. + + // Set by libretro core. Called after camera driver is initialized and ready to be started. + // Can be NULL, in which this callback is not called. + retro_camera_lifetime_status_t initialized; + + // Set by libretro core. Called right before camera driver is deinitialized. + // Can be NULL, in which this callback is not called. + retro_camera_lifetime_status_t deinitialized; +}; + +enum retro_rumble_effect +{ + RETRO_RUMBLE_STRONG = 0, + RETRO_RUMBLE_WEAK = 1, + + RETRO_RUMBLE_DUMMY = INT_MAX +}; + +// Sets rumble state for joypad plugged in port 'port'. Rumble effects are controlled independently, +// and setting e.g. strong rumble does not override weak rumble. +// Strength has a range of [0, 0xffff]. +// +// Returns true if rumble state request was honored. Calling this before first retro_run() is likely to return false. +typedef bool (*retro_set_rumble_state_t)(unsigned port, enum retro_rumble_effect effect, uint16_t strength); +struct retro_rumble_interface +{ + retro_set_rumble_state_t set_rumble_state; +}; + +// Notifies libretro that audio data should be written. +typedef void (*retro_audio_callback_t)(void); + +// True: Audio driver in frontend is active, and callback is expected to be called regularily. +// False: Audio driver in frontend is paused or inactive. Audio callback will not be called until set_state has been called with true. +// Initial state is false (inactive). +typedef void (*retro_audio_set_state_callback_t)(bool enabled); +struct retro_audio_callback +{ + retro_audio_callback_t callback; + retro_audio_set_state_callback_t set_state; +}; + +// Notifies a libretro core of time spent since last invocation of retro_run() in microseconds. +// It will be called right before retro_run() every frame. +// The frontend can tamper with timing to support cases like fast-forward, slow-motion and framestepping. +// In those scenarios the reference frame time value will be used. +typedef int64_t retro_usec_t; +typedef void (*retro_frame_time_callback_t)(retro_usec_t usec); +struct retro_frame_time_callback +{ + retro_frame_time_callback_t callback; + retro_usec_t reference; // Represents the time of one frame. It is computed as 1000000 / fps, but the implementation will resolve the rounding to ensure that framestepping, etc is exact. +}; // Pass this to retro_video_refresh_t if rendering to hardware. // Passing NULL to retro_video_refresh_t is still a frame dupe as normal. #define RETRO_HW_FRAME_BUFFER_VALID ((void*)-1) // Invalidates the current HW context. +// Any GL state is lost, and must not be deinitialized explicitly. If explicit deinitialization is desired by the libretro core, +// it should implement context_destroy callback. // If called, all GPU resources must be reinitialized. // Usually called when frontend reinits video driver. // Also called first time video driver is initialized, allowing libretro core to init resources. @@ -479,8 +808,10 @@ typedef retro_proc_address_t (*retro_hw_get_proc_address_t)(const char *sym); enum retro_hw_context_type { RETRO_HW_CONTEXT_NONE = 0, - RETRO_HW_CONTEXT_OPENGL, // OpenGL 2.x. Latest version available before 3.x+. + RETRO_HW_CONTEXT_OPENGL, // OpenGL 2.x. Latest version available before 3.x+. Driver can choose to use latest compatibility context. RETRO_HW_CONTEXT_OPENGLES2, // GLES 2.0 + RETRO_HW_CONTEXT_OPENGL_CORE, // Modern desktop core GL context. Use major/minor fields to set GL version. + RETRO_HW_CONTEXT_OPENGLES3, // GLES 3.0 RETRO_HW_CONTEXT_DUMMY = INT_MAX }; @@ -488,10 +819,21 @@ enum retro_hw_context_type struct retro_hw_render_callback { enum retro_hw_context_type context_type; // Which API to use. Set by libretro core. - retro_hw_context_reset_t context_reset; // Set by libretro core. + retro_hw_context_reset_t context_reset; // Called when a context has been created or when it has been reset. retro_hw_get_current_framebuffer_t get_current_framebuffer; // Set by frontend. retro_hw_get_proc_address_t get_proc_address; // Set by frontend. bool depth; // Set if render buffers should have depth component attached. + bool stencil; // Set if stencil buffers should be attached. + // If depth and stencil are true, a packed 24/8 buffer will be added. Only attaching stencil is invalid and will be ignored. + bool bottom_left_origin; // Use conventional bottom-left origin convention. Is false, standard libretro top-left origin semantics are used. + unsigned version_major; // Major version number for core GL context. + unsigned version_minor; // Minor version number for core GL context. + + bool cache_context; // If this is true, the frontend will go very far to avoid resetting context in scenarios like toggling fullscreen, etc. + // The reset callback might still be called in extreme situations such as if the context is lost beyond recovery. + // For optimal stability, set this to false, and allow context to be reset at any time. + retro_hw_context_reset_t context_destroy; // A callback to be called before the context is destroyed. Resources can be deinitialized at this step. This can be set to NULL, in which resources will just be destroyed without any notification. + bool debug_context; // Creates a debug context. }; // Callback type passed in RETRO_ENVIRONMENT_SET_KEYBOARD_CALLBACK. Called by the frontend in response to keyboard events. @@ -499,6 +841,13 @@ struct retro_hw_render_callback // keycode is the RETROK value of the char. // character is the text character of the pressed key. (UTF-32). // key_modifiers is a set of RETROKMOD values or'ed together. +// +// The pressed/keycode state can be indepedent of the character. +// It is also possible that multiple characters are generated from a single keypress. +// Keycode events should be treated separately from character events. +// However, when possible, the frontend should try to synchronize these. +// If only a character is posted, keycode should be RETROK_UNKNOWN. +// Similarily if only a keycode event is generated with no corresponding character, character should be 0. typedef void (*retro_keyboard_event_t)(bool down, unsigned keycode, uint32_t character, uint16_t key_modifiers); struct retro_keyboard_callback -- cgit v1.2.3 From f543ae2baef4ba714d7b061f0fa374a374fa79d5 Mon Sep 17 00:00:00 2001 From: meancoot Date: Thu, 19 Dec 2013 16:53:46 -0500 Subject: (iOS) Work around clang crash when compiling libpcsxcor/new_dynarec/pcsxmem.c. --- Makefile.libretro | 5 ----- libpcsxcore/new_dynarec/pcsxmem.c | 5 +++++ 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Makefile.libretro b/Makefile.libretro index 6f7b29a..8b4a61b 100644 --- a/Makefile.libretro +++ b/Makefile.libretro @@ -144,11 +144,6 @@ NO_CONFIG_MAK = yes include Makefile -# workaround segfault for this file seen on: -# Apple LLVM version 4.2 (clang-425.0.27) (based on LLVM 3.2svn) -libpcsxcore/new_dynarec/pcsxmem.o: libpcsxcore/new_dynarec/pcsxmem.c - $(CC) -c -o $@ $< $(CPPFLAGS) $(CFLAGS) -Os - # no special AS needed for gpu_neon plugins/gpu_neon/psx_gpu/psx_gpu_arm_neon.o: plugins/gpu_neon/psx_gpu/psx_gpu_arm_neon.S $(CC) $(CFLAGS) -c $^ -o $@ diff --git a/libpcsxcore/new_dynarec/pcsxmem.c b/libpcsxcore/new_dynarec/pcsxmem.c index 3d14904..0a75442 100644 --- a/libpcsxcore/new_dynarec/pcsxmem.c +++ b/libpcsxcore/new_dynarec/pcsxmem.c @@ -30,7 +30,12 @@ static u32 mem_ffwtab[(1+2+4) * 0x1000 / 4]; //static u32 mem_unmrtab[(1+2+4) * 0x1000 / 4]; static u32 mem_unmwtab[(1+2+4) * 0x1000 / 4]; +// When this is called in a loop, and 'h' is a function pointer, clang will crash. +#ifdef __clang__ +static __attribute__ ((noinline)) void map_item(u32 *out, const void *h, u32 flag) +#else static void map_item(u32 *out, const void *h, u32 flag) +#endif { u32 hv = (u32)h; if (hv & 1) { -- cgit v1.2.3 From c82d5b4ba31ae828cae27962f1a4d328fd4ea4da Mon Sep 17 00:00:00 2001 From: twinaphex Date: Tue, 31 Dec 2013 04:55:09 +0100 Subject: Fixed NEON GPU plugin for PC by using stdint.h types - use NEON GPU plugin for non-ARM targets now --- Makefile | 8 +++++++- Makefile.libretro | 6 ++++++ frontend/libretro.c | 5 +++-- plugins/gpu_neon/psx_gpu/common.h | 14 +++++++++++++- plugins/gpu_neon/psx_gpu/psx_gpu.c | 4 ++++ plugins/gpu_neon/psx_gpu_if.c | 2 +- 6 files changed, 34 insertions(+), 5 deletions(-) diff --git a/Makefile b/Makefile index cc19e77..6187958 100644 --- a/Makefile +++ b/Makefile @@ -107,9 +107,15 @@ endif # builtin gpu OBJS += plugins/gpulib/gpu.o plugins/gpulib/vout_pl.o ifeq "$(BUILTIN_GPU)" "neon" -OBJS += plugins/gpu_neon/psx_gpu_if.o plugins/gpu_neon/psx_gpu/psx_gpu_arm_neon.o +ifeq "$(HAVE_NEON)" "1" plugins/gpu_neon/psx_gpu_if.o: CFLAGS += -DNEON_BUILD -DTEXTURE_CACHE_4BPP -DTEXTURE_CACHE_8BPP plugins/gpu_neon/psx_gpu_if.o: plugins/gpu_neon/psx_gpu/*.c +OBJS += plugins/gpu_neon/psx_gpu_if.o plugins/gpu_neon/psx_gpu/psx_gpu_arm_neon.o +else +plugins/gpu_neon/psx_gpu_if.o: CFLAGS += -DTEXTURE_CACHE_4BPP -DTEXTURE_CACHE_8BPP +plugins/gpu_neon/psx_gpu_if.o: plugins/gpu_neon/psx_gpu/*.c +OBJS += plugins/gpu_neon/psx_gpu_if.o +endif endif ifeq "$(BUILTIN_GPU)" "peops" # note: code is not safe for strict-aliasing? (Castlevania problems) diff --git a/Makefile.libretro b/Makefile.libretro index 8b4a61b..d9ab7a0 100644 --- a/Makefile.libretro +++ b/Makefile.libretro @@ -25,10 +25,14 @@ ifeq ($(platform), unix) TARGET := $(TARGET_NAME)_libretro.so fpic := -fPIC SHARED := -shared -Wl,--version-script=libretro/link.T + BUILTIN_GPU = neon + CFLAGS += -DNEON_PC else ifeq ($(platform), osx) TARGET := $(TARGET_NAME)_libretro.dylib fpic := -fPIC SHARED := -dynamiclib + BUILTIN_GPU = neon + CFLAGS += -DNEON_PC else ifeq ($(platform), ios) ARCH := arm TARGET := $(TARGET_NAME)_libretro_ios.dylib @@ -124,6 +128,8 @@ else LD_FLAGS := -fPIC SHARED := -shared -static-libgcc -static-libstdc++ -s -Wl,--version-script=libretro/link.T CFLAGS += -D__WIN32__ -D__WIN32_LIBRETRO__ + BUILTIN_GPU = neon + CFLAGS += -DNEON_PC endif CFLAGS += -fPIC diff --git a/frontend/libretro.c b/frontend/libretro.c index 23eecf6..bce05e8 100644 --- a/frontend/libretro.c +++ b/frontend/libretro.c @@ -246,7 +246,7 @@ void retro_set_environment(retro_environment_t cb) #ifndef DRC_DISABLE { "rearmed_drc", "Dynamic recompiler; enabled|disabled" }, #endif -#ifdef __ARM_NEON__ +#if defined(__ARM_NEON__) || defined(NEON_PC) { "neon_interlace_enable", "Enable interlacing mode(s); disabled|enabled" }, { "neon_enhancement_enable", "Enhanced resolution (slow); disabled|enabled" }, { "neon_enhancement_no_main", "Enhanced resolution speed hack; disabled|enabled" }, @@ -800,7 +800,7 @@ static void update_variables(bool in_flight) in_type1 = PSE_PAD_TYPE_ANALOGPAD; } -#ifdef __ARM_NEON__ +#if defined(__ARM_NEON__) || defined(NEON_PC) var.value = "NULL"; var.key = "neon_interlace_enable"; @@ -834,6 +834,7 @@ static void update_variables(bool in_flight) pl_rearmed_cbs.gpu_neon.enhancement_no_main = 1; } #endif + #ifndef DRC_DISABLE var.value = NULL; var.key = "rearmed_drc"; diff --git a/plugins/gpu_neon/psx_gpu/common.h b/plugins/gpu_neon/psx_gpu/common.h index d5cf3e9..6c2a99b 100644 --- a/plugins/gpu_neon/psx_gpu/common.h +++ b/plugins/gpu_neon/psx_gpu/common.h @@ -1,6 +1,18 @@ #ifndef COMMON_H #define COMMON_H +#include + +#ifdef NEON_PC +typedef int8_t s8; +typedef uint8_t u8; +typedef int16_t s16; +typedef uint16_t u16; +typedef int32_t s32; +typedef uint32_t u32; +typedef int64_t s64; +typedef uint64_t u64; +#else typedef signed char s8; typedef unsigned char u8; typedef signed short s16; @@ -9,8 +21,8 @@ typedef signed int s32; typedef unsigned int u32; typedef signed long long int s64; typedef unsigned long long int u64; +#endif -#include #include #include #include diff --git a/plugins/gpu_neon/psx_gpu/psx_gpu.c b/plugins/gpu_neon/psx_gpu/psx_gpu.c index e113f06..24f663b 100644 --- a/plugins/gpu_neon/psx_gpu/psx_gpu.c +++ b/plugins/gpu_neon/psx_gpu/psx_gpu.c @@ -4130,7 +4130,11 @@ void setup_sprite_untextured_simple(psx_gpu_struct *psx_gpu, s32 x, s32 y, num_width = width; vram_ptr = (void *)vram_ptr16; +#ifdef NEON_PC + if((int32_t)vram_ptr16 & 2) +#else if((long)vram_ptr16 & 2) +#endif { *vram_ptr16 = color_32bpp; vram_ptr = (void *)(vram_ptr16 + 1); diff --git a/plugins/gpu_neon/psx_gpu_if.c b/plugins/gpu_neon/psx_gpu_if.c index ad01761..86103f3 100644 --- a/plugins/gpu_neon/psx_gpu_if.c +++ b/plugins/gpu_neon/psx_gpu_if.c @@ -8,7 +8,7 @@ * See the COPYING file in the top-level directory. */ -#include +#include #include extern const unsigned char cmd_lengths[256]; -- cgit v1.2.3 From 483afec9ee6cec490e692d0a4f8113d8749e939c Mon Sep 17 00:00:00 2001 From: twinaphex Date: Tue, 31 Dec 2013 05:19:20 +0100 Subject: (Libretro) Add frame duping core option --- frontend/libretro.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/frontend/libretro.c b/frontend/libretro.c index bce05e8..5a881f3 100644 --- a/frontend/libretro.c +++ b/frontend/libretro.c @@ -37,6 +37,7 @@ static void *vout_buf; static int vout_width, vout_height; static int vout_doffs_old, vout_fb_dirty; static bool vout_can_dupe; +static bool duping_enable; static int samples_sent, samples_to_send; static int plugins_opened; @@ -251,6 +252,7 @@ void retro_set_environment(retro_environment_t cb) { "neon_enhancement_enable", "Enhanced resolution (slow); disabled|enabled" }, { "neon_enhancement_no_main", "Enhanced resolution speed hack; disabled|enabled" }, #endif + { "pcsx_rearmed_duping_enable", "Frame duping; on|off" }, { NULL, NULL }, }; @@ -835,6 +837,17 @@ static void update_variables(bool in_flight) } #endif + var.value = "NULL"; + var.key = "pcsx_rearmed_duping_enable"; + + if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) || var.value) + { + if (strcmp(var.value, "off") == 0) + duping_enable = false; + else if (strcmp(var.value, "on") == 0) + duping_enable = true; + } + #ifndef DRC_DISABLE var.value = NULL; var.key = "rearmed_drc"; @@ -902,7 +915,7 @@ void retro_run(void) samples_to_send += is_pal_mode ? 44100 / 50 : 44100 / 60; - video_cb((vout_fb_dirty || !vout_can_dupe) ? vout_buf : NULL, + video_cb((vout_fb_dirty || !vout_can_dupe || !duping_enable) ? vout_buf : NULL, vout_width, vout_height, vout_width * 2); vout_fb_dirty = 0; } -- cgit v1.2.3 From 3addc00a913ee3dac6729a87aa059703a1f12d02 Mon Sep 17 00:00:00 2001 From: twinaphex Date: Fri, 3 Jan 2014 17:44:01 +0100 Subject: (OSX) Set min OS version to 10.6 --- Makefile.libretro | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile.libretro b/Makefile.libretro index d9ab7a0..62044b4 100644 --- a/Makefile.libretro +++ b/Makefile.libretro @@ -29,7 +29,7 @@ ifeq ($(platform), unix) CFLAGS += -DNEON_PC else ifeq ($(platform), osx) TARGET := $(TARGET_NAME)_libretro.dylib - fpic := -fPIC + fpic := -fPIC -mmacosx-version-min=10.6 SHARED := -dynamiclib BUILTIN_GPU = neon CFLAGS += -DNEON_PC -- cgit v1.2.3 From 252e4935160ab66db53edc2da74ea5967c5eaf5f Mon Sep 17 00:00:00 2001 From: Tobias Jakobi Date: Tue, 4 Mar 2014 20:15:13 +0100 Subject: libretro: align vout_buf to 128-bit --- frontend/libretro.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/libretro.c b/frontend/libretro.c index 5a881f3..13a4af3 100644 --- a/frontend/libretro.c +++ b/frontend/libretro.c @@ -989,7 +989,7 @@ void retro_init(void) exit(1); } - vout_buf = malloc(VOUT_MAX_WIDTH * VOUT_MAX_HEIGHT * 2); + posix_memalign(&vout_buf, 16, VOUT_MAX_WIDTH * VOUT_MAX_HEIGHT * 2); if (environ_cb(RETRO_ENVIRONMENT_GET_SYSTEM_DIRECTORY, &dir) && dir) { -- cgit v1.2.3 From 63d480d0376b617a2775cc5a2fc323b68207748b Mon Sep 17 00:00:00 2001 From: Tobias Jakobi Date: Tue, 4 Mar 2014 21:55:15 +0100 Subject: libretro: only use posix_memalign when it's safe --- frontend/libretro.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/frontend/libretro.c b/frontend/libretro.c index 13a4af3..b8dc36d 100644 --- a/frontend/libretro.c +++ b/frontend/libretro.c @@ -989,7 +989,11 @@ void retro_init(void) exit(1); } +#if defined(_POSIX_C_SOURCE) && (_POSIX_C_SOURCE >= 200112L) posix_memalign(&vout_buf, 16, VOUT_MAX_WIDTH * VOUT_MAX_HEIGHT * 2); +#else + vout_buf = malloc(VOUT_MAX_WIDTH * VOUT_MAX_HEIGHT * 2); +#endif if (environ_cb(RETRO_ENVIRONMENT_GET_SYSTEM_DIRECTORY, &dir) && dir) { -- cgit v1.2.3 From 9c79adfd39d78c3b615a7ac0ef4ce472439808ce Mon Sep 17 00:00:00 2001 From: twinaphex Date: Sat, 26 Apr 2014 05:30:46 +0200 Subject: Add OSX version minor detection to Makefile --- Makefile.libretro | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/Makefile.libretro b/Makefile.libretro index 62044b4..0621d18 100644 --- a/Makefile.libretro +++ b/Makefile.libretro @@ -29,25 +29,36 @@ ifeq ($(platform), unix) CFLAGS += -DNEON_PC else ifeq ($(platform), osx) TARGET := $(TARGET_NAME)_libretro.dylib - fpic := -fPIC -mmacosx-version-min=10.6 + fpic := -fPIC SHARED := -dynamiclib BUILTIN_GPU = neon CFLAGS += -DNEON_PC +OSXVER = `sw_vers -productVersion | cut -c 4` +ifneq ($(OSXVER),9) + fpic += -mmacosx-version-min=10.5 +endif else ifeq ($(platform), ios) ARCH := arm TARGET := $(TARGET_NAME)_libretro_ios.dylib fpic := -fPIC SHARED := -dynamiclib - CC = clang -arch armv7 -isysroot $(IOSSDK) -miphoneos-version-min=5.0 - CXX = clang++ -arch armv7 -isysroot $(IOSSDK) -miphoneos-version-min=5.0 - CC_AS = perl ./tools/gas-preprocessor.pl $(CC) -miphoneos-version-min=5.0 - CFLAGS += -mcpu=cortex-a8 -mtune=cortex-a8 -mfpu=neon -marm -miphoneos-version-min=5.0 + CC = clang -arch armv7 -isysroot $(IOSSDK) + CXX = clang++ -arch armv7 -isysroot $(IOSSDK) + CC_AS = perl ./tools/gas-preprocessor.pl $(CC) + CFLAGS += -mcpu=cortex-a8 -mtune=cortex-a8 -mfpu=neon -marm ASFLAGS += -mcpu=cortex-a8 -mtune=cortex-a8 -mfpu=neon HAVE_NEON = 1 BUILTIN_GPU = neon USE_DYNAREC = 1 - CFLAGS += -DIOS -miphoneos-version-min=5.0 + CFLAGS += -DIOS +OSXVER = `sw_vers -productVersion | cut -c 4` +ifneq ($(OSXVER),9) + CC += -miphoneos-version-min=5.0 + CXX += -miphoneos-version-min=5.0 + CC_AS += -miphoneos-version-min=5.0 + CFLAGS += -miphoneos-version-min=5.0 +endif else ifeq ($(platform), ps3) TARGET := $(TARGET_NAME)_libretro_ps3.a CC = $(CELL_SDK)/host-win32/ppu/bin/ppu-lv2-gcc.exe -- cgit v1.2.3 From 496d5596907024138ae72cda9eed05c92a697d18 Mon Sep 17 00:00:00 2001 From: twinaphex Date: Mon, 23 Jun 2014 15:02:13 +0200 Subject: Set performance level --- frontend/libretro.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/frontend/libretro.c b/frontend/libretro.c index b8dc36d..c7c14c0 100644 --- a/frontend/libretro.c +++ b/frontend/libretro.c @@ -974,6 +974,12 @@ static bool find_any_bios(const char *dirpath, char *path, size_t path_size) #define find_any_bios(...) false #endif +static void check_system_specs(void) +{ + unsigned level = 6; + environ_cb(RETRO_ENVIRONMENT_SET_PERFORMANCE_LEVEL, &level); +} + void retro_init(void) { const char *bios[] = { "scph1001", "scph5501", "scph7001" }; @@ -1049,6 +1055,7 @@ void retro_init(void) SaveFuncs.close = save_close; update_variables(false); + check_system_specs(); } void retro_deinit(void) -- cgit v1.2.3 From d9849c9a5ea08171671a75cd499fefc26e9747b5 Mon Sep 17 00:00:00 2001 From: twinaphex Date: Wed, 30 Jul 2014 17:05:21 +0200 Subject: Makefile - fixup Windows build --- Makefile.libretro | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile.libretro b/Makefile.libretro index 0621d18..7c16422 100644 --- a/Makefile.libretro +++ b/Makefile.libretro @@ -133,7 +133,7 @@ endif ARCH = arm USE_DYNAREC = 1 else - TARGET := $(TARGET_NAME)_retro.dll + TARGET := $(TARGET_NAME)_libretro.dll CC = gcc fpic := -fPIC LD_FLAGS := -fPIC -- cgit v1.2.3 From a19f6faa80beabe1137a766c4c5c508d7b84ebb4 Mon Sep 17 00:00:00 2001 From: Tobias Jakobi Date: Wed, 6 Aug 2014 19:51:29 +0200 Subject: libretro: adjust indentation style The indentation style should be at least consistent inside a single function. --- frontend/libretro.c | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/frontend/libretro.c b/frontend/libretro.c index c7c14c0..e5496cb 100644 --- a/frontend/libretro.c +++ b/frontend/libretro.c @@ -870,17 +870,17 @@ static void update_variables(bool in_flight) } #endif - if (in_flight) { - // inform core things about possible config changes - plugin_call_rearmed_cbs(); + if (in_flight) { + // inform core things about possible config changes + plugin_call_rearmed_cbs(); - if (GPU_open != NULL && GPU_close != NULL) { - GPU_close(); - GPU_open(&gpuDisp, "PCSX", NULL); - } + if (GPU_open != NULL && GPU_close != NULL) { + GPU_close(); + GPU_open(&gpuDisp, "PCSX", NULL); + } - dfinput_activate(); - } + dfinput_activate(); + } } void retro_run(void) @@ -902,13 +902,13 @@ void retro_run(void) if (input_state_cb(0, RETRO_DEVICE_JOYPAD, 0, i)) in_keystate |= retro_psx_map[i]; - if (in_type1 == PSE_PAD_TYPE_ANALOGPAD) - { - in_a1[0] = (input_state_cb(0, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_LEFT, RETRO_DEVICE_ID_ANALOG_X) / 256) + 128; - in_a1[1] = (input_state_cb(0, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_LEFT, RETRO_DEVICE_ID_ANALOG_Y) / 256) + 128; - in_a2[0] = (input_state_cb(0, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_RIGHT, RETRO_DEVICE_ID_ANALOG_X) / 256) + 128; - in_a2[1] = (input_state_cb(0, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_RIGHT, RETRO_DEVICE_ID_ANALOG_Y) / 256) + 128; - } + if (in_type1 == PSE_PAD_TYPE_ANALOGPAD) + { + in_a1[0] = (input_state_cb(0, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_LEFT, RETRO_DEVICE_ID_ANALOG_X) / 256) + 128; + in_a1[1] = (input_state_cb(0, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_LEFT, RETRO_DEVICE_ID_ANALOG_Y) / 256) + 128; + in_a2[0] = (input_state_cb(0, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_RIGHT, RETRO_DEVICE_ID_ANALOG_X) / 256) + 128; + in_a2[1] = (input_state_cb(0, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_RIGHT, RETRO_DEVICE_ID_ANALOG_Y) / 256) + 128; + } stop = 0; psxCpu->Execute(); @@ -1055,7 +1055,7 @@ void retro_init(void) SaveFuncs.close = save_close; update_variables(false); - check_system_specs(); + check_system_specs(); } void retro_deinit(void) -- cgit v1.2.3 From eae1ae02468e1d9d106fd39772a980e5cf3ffb31 Mon Sep 17 00:00:00 2001 From: Alcaro Date: Mon, 22 Sep 2014 22:20:10 +0000 Subject: Update libretro.h --- frontend/libretro.h | 1916 ++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 1364 insertions(+), 552 deletions(-) diff --git a/frontend/libretro.h b/frontend/libretro.h index ede60f0..16c274a 100755 --- a/frontend/libretro.h +++ b/frontend/libretro.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2013 The RetroArch team +/* Copyright (C) 2010-2014 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this libretro API header (libretro.h). @@ -27,11 +27,14 @@ #include #include -// Hack applied for MSVC when compiling in C89 mode as it isn't C99 compliant. #ifdef __cplusplus extern "C" { -#else -#if defined(_MSC_VER) && !defined(SN_TARGET_PS3) && !defined(__cplusplus) +#endif + +#ifndef __cplusplus +#if defined(_MSC_VER) && !defined(SN_TARGET_PS3) +/* Hack applied for MSVC when compiling in C89 mode + * as it isn't C99-compliant. */ #define bool unsigned char #define true 1 #define false 0 @@ -40,76 +43,104 @@ extern "C" { #endif #endif -// Used for checking API/ABI mismatches that can break libretro implementations. -// It is not incremented for compatible changes to the API. +/* Used for checking API/ABI mismatches that can break libretro + * implementations. + * It is not incremented for compatible changes to the API. + */ #define RETRO_API_VERSION 1 -// Libretro's fundamental device abstractions. -#define RETRO_DEVICE_MASK 0xff +/* + * Libretro's fundamental device abstractions. + * + * Libretro's input system consists of some standardized device types, + * such as a joypad (with/without analog), mouse, keyboard, lightgun + * and a pointer. + * + * The functionality of these devices are fixed, and individual cores + * map their own concept of a controller to libretro's abstractions. + * This makes it possible for frontends to map the abstract types to a + * real input device, and not having to worry about binding input + * correctly to arbitrary controller layouts. + */ + +#define RETRO_DEVICE_TYPE_SHIFT 8 +#define RETRO_DEVICE_MASK ((1 << RETRO_DEVICE_TYPE_SHIFT) - 1) +#define RETRO_DEVICE_SUBCLASS(base, id) (((id + 1) << RETRO_DEVICE_TYPE_SHIFT) | base) + +/* Input disabled. */ #define RETRO_DEVICE_NONE 0 -// The JOYPAD is called RetroPad. It is essentially a Super Nintendo controller, -// but with additional L2/R2/L3/R3 buttons, similar to a PS1 DualShock. +/* The JOYPAD is called RetroPad. It is essentially a Super Nintendo + * controller, but with additional L2/R2/L3/R3 buttons, similar to a + * PS1 DualShock. */ #define RETRO_DEVICE_JOYPAD 1 -// The mouse is a simple mouse, similar to Super Nintendo's mouse. -// X and Y coordinates are reported relatively to last poll (poll callback). -// It is up to the libretro implementation to keep track of where the mouse pointer is supposed to be on the screen. -// The frontend must make sure not to interfere with its own hardware mouse pointer. +/* The mouse is a simple mouse, similar to Super Nintendo's mouse. + * X and Y coordinates are reported relatively to last poll (poll callback). + * It is up to the libretro implementation to keep track of where the mouse + * pointer is supposed to be on the screen. + * The frontend must make sure not to interfere with its own hardware + * mouse pointer. + */ #define RETRO_DEVICE_MOUSE 2 -// KEYBOARD device lets one poll for raw key pressed. -// It is poll based, so input callback will return with the current pressed state. +/* KEYBOARD device lets one poll for raw key pressed. + * It is poll based, so input callback will return with the current + * pressed state. + * For event/text based keyboard input, see + * RETRO_ENVIRONMENT_SET_KEYBOARD_CALLBACK. + */ #define RETRO_DEVICE_KEYBOARD 3 -// Lightgun X/Y coordinates are reported relatively to last poll, similar to mouse. +/* Lightgun X/Y coordinates are reported relatively to last poll, + * similar to mouse. */ #define RETRO_DEVICE_LIGHTGUN 4 -// The ANALOG device is an extension to JOYPAD (RetroPad). -// Similar to DualShock it adds two analog sticks. -// This is treated as a separate device type as it returns values in the full analog range -// of [-0x8000, 0x7fff]. Positive X axis is right. Positive Y axis is down. -// Only use ANALOG type when polling for analog values of the axes. +/* The ANALOG device is an extension to JOYPAD (RetroPad). + * Similar to DualShock it adds two analog sticks. + * This is treated as a separate device type as it returns values in the + * full analog range of [-0x8000, 0x7fff]. Positive X axis is right. + * Positive Y axis is down. + * Only use ANALOG type when polling for analog values of the axes. + */ #define RETRO_DEVICE_ANALOG 5 -// Abstracts the concept of a pointing mechanism, e.g. touch. -// This allows libretro to query in absolute coordinates where on the screen a mouse (or something similar) is being placed. -// For a touch centric device, coordinates reported are the coordinates of the press. -// -// Coordinates in X and Y are reported as: -// [-0x7fff, 0x7fff]: -0x7fff corresponds to the far left/top of the screen, -// and 0x7fff corresponds to the far right/bottom of the screen. -// The "screen" is here defined as area that is passed to the frontend and later displayed on the monitor. -// The frontend is free to scale/resize this screen as it sees fit, however, -// (X, Y) = (-0x7fff, -0x7fff) will correspond to the top-left pixel of the game image, etc. -// -// To check if the pointer coordinates are valid (e.g. a touch display actually being touched), -// PRESSED returns 1 or 0. -// If using a mouse, PRESSED will usually correspond to the left mouse button. -// PRESSED will only return 1 if the pointer is inside the game screen. -// -// For multi-touch, the index variable can be used to successively query more presses. -// If index = 0 returns true for _PRESSED, coordinates can be extracted -// with _X, _Y for index = 0. One can then query _PRESSED, _X, _Y with index = 1, and so on. -// Eventually _PRESSED will return false for an index. No further presses are registered at this point. +/* Abstracts the concept of a pointing mechanism, e.g. touch. + * This allows libretro to query in absolute coordinates where on the + * screen a mouse (or something similar) is being placed. + * For a touch centric device, coordinates reported are the coordinates + * of the press. + * + * Coordinates in X and Y are reported as: + * [-0x7fff, 0x7fff]: -0x7fff corresponds to the far left/top of the screen, + * and 0x7fff corresponds to the far right/bottom of the screen. + * The "screen" is here defined as area that is passed to the frontend and + * later displayed on the monitor. + * + * The frontend is free to scale/resize this screen as it sees fit, however, + * (X, Y) = (-0x7fff, -0x7fff) will correspond to the top-left pixel of the + * game image, etc. + * + * To check if the pointer coordinates are valid (e.g. a touch display + * actually being touched), PRESSED returns 1 or 0. + * + * If using a mouse on a desktop, PRESSED will usually correspond to the + * left mouse button, but this is a frontend decision. + * PRESSED will only return 1 if the pointer is inside the game screen. + * + * For multi-touch, the index variable can be used to successively query + * more presses. + * If index = 0 returns true for _PRESSED, coordinates can be extracted + * with _X, _Y for index = 0. One can then query _PRESSED, _X, _Y with + * index = 1, and so on. + * Eventually _PRESSED will return false for an index. No further presses + * are registered at this point. */ #define RETRO_DEVICE_POINTER 6 -// FIXME: Document this. -#define RETRO_DEVICE_SENSOR_ACCELEROMETER 7 - -// These device types are specializations of the base types above. -// They should only be used in retro_set_controller_type() to inform libretro implementations -// about use of a very specific device type. -// -// In input state callback, however, only the base type should be used in the 'device' field. -#define RETRO_DEVICE_JOYPAD_MULTITAP ((1 << 8) | RETRO_DEVICE_JOYPAD) -#define RETRO_DEVICE_LIGHTGUN_SUPER_SCOPE ((1 << 8) | RETRO_DEVICE_LIGHTGUN) -#define RETRO_DEVICE_LIGHTGUN_JUSTIFIER ((2 << 8) | RETRO_DEVICE_LIGHTGUN) -#define RETRO_DEVICE_LIGHTGUN_JUSTIFIERS ((3 << 8) | RETRO_DEVICE_LIGHTGUN) - -// Buttons for the RetroPad (JOYPAD). -// The placement of these is equivalent to placements on the Super Nintendo controller. -// L2/R2/L3/R3 buttons correspond to the PS1 DualShock. +/* Buttons for the RetroPad (JOYPAD). + * The placement of these is equivalent to placements on the + * Super Nintendo controller. + * L2/R2/L3/R3 buttons correspond to the PS1 DualShock. */ #define RETRO_DEVICE_ID_JOYPAD_B 0 #define RETRO_DEVICE_ID_JOYPAD_Y 1 #define RETRO_DEVICE_ID_JOYPAD_SELECT 2 @@ -127,19 +158,22 @@ extern "C" { #define RETRO_DEVICE_ID_JOYPAD_L3 14 #define RETRO_DEVICE_ID_JOYPAD_R3 15 -// Index / Id values for ANALOG device. +/* Index / Id values for ANALOG device. */ #define RETRO_DEVICE_INDEX_ANALOG_LEFT 0 #define RETRO_DEVICE_INDEX_ANALOG_RIGHT 1 #define RETRO_DEVICE_ID_ANALOG_X 0 #define RETRO_DEVICE_ID_ANALOG_Y 1 -// Id values for MOUSE. -#define RETRO_DEVICE_ID_MOUSE_X 0 -#define RETRO_DEVICE_ID_MOUSE_Y 1 -#define RETRO_DEVICE_ID_MOUSE_LEFT 2 -#define RETRO_DEVICE_ID_MOUSE_RIGHT 3 +/* Id values for MOUSE. */ +#define RETRO_DEVICE_ID_MOUSE_X 0 +#define RETRO_DEVICE_ID_MOUSE_Y 1 +#define RETRO_DEVICE_ID_MOUSE_LEFT 2 +#define RETRO_DEVICE_ID_MOUSE_RIGHT 3 +#define RETRO_DEVICE_ID_MOUSE_WHEELUP 4 +#define RETRO_DEVICE_ID_MOUSE_WHEELDOWN 5 +#define RETRO_DEVICE_ID_MOUSE_MIDDLE 6 -// Id values for LIGHTGUN types. +/* Id values for LIGHTGUN types. */ #define RETRO_DEVICE_ID_LIGHTGUN_X 0 #define RETRO_DEVICE_ID_LIGHTGUN_Y 1 #define RETRO_DEVICE_ID_LIGHTGUN_TRIGGER 2 @@ -148,55 +182,61 @@ extern "C" { #define RETRO_DEVICE_ID_LIGHTGUN_PAUSE 5 #define RETRO_DEVICE_ID_LIGHTGUN_START 6 -// Id values for POINTER. +/* Id values for POINTER. */ #define RETRO_DEVICE_ID_POINTER_X 0 #define RETRO_DEVICE_ID_POINTER_Y 1 #define RETRO_DEVICE_ID_POINTER_PRESSED 2 -// Id values for SENSOR types. -#define RETRO_DEVICE_ID_SENSOR_ACCELEROMETER_X 0 -#define RETRO_DEVICE_ID_SENSOR_ACCELEROMETER_Y 1 -#define RETRO_DEVICE_ID_SENSOR_ACCELEROMETER_Z 2 - -// Returned from retro_get_region(). +/* Returned from retro_get_region(). */ #define RETRO_REGION_NTSC 0 #define RETRO_REGION_PAL 1 -// Passed to retro_get_memory_data/size(). -// If the memory type doesn't apply to the implementation NULL/0 can be returned. +/* Id values for LANGUAGE */ +enum retro_language +{ + RETRO_LANGUAGE_ENGLISH = 0, + RETRO_LANGUAGE_JAPANESE = 1, + RETRO_LANGUAGE_FRENCH = 2, + RETRO_LANGUAGE_SPANISH = 3, + RETRO_LANGUAGE_GERMAN = 4, + RETRO_LANGUAGE_ITALIAN = 5, + RETRO_LANGUAGE_DUTCH = 6, + RETRO_LANGUAGE_PORTUGUESE = 7, + RETRO_LANGUAGE_RUSSIAN = 8, + RETRO_LANGUAGE_KOREAN = 9, + RETRO_LANGUAGE_CHINESE_TRADITIONAL = 10, + RETRO_LANGUAGE_CHINESE_SIMPLIFIED = 11, + RETRO_LANGUAGE_LAST, + + /* Ensure sizeof(enum) == sizeof(int) */ + RETRO_LANGUAGE_DUMMY = INT_MAX +}; + +/* Passed to retro_get_memory_data/size(). + * If the memory type doesn't apply to the + * implementation NULL/0 can be returned. + */ #define RETRO_MEMORY_MASK 0xff -// Regular save ram. This ram is usually found on a game cartridge, backed up by a battery. -// If save game data is too complex for a single memory buffer, -// the SYSTEM_DIRECTORY environment callback can be used. +/* Regular save RAM. This RAM is usually found on a game cartridge, + * backed up by a battery. + * If save game data is too complex for a single memory buffer, + * the SAVE_DIRECTORY (preferably) or SYSTEM_DIRECTORY environment + * callback can be used. */ #define RETRO_MEMORY_SAVE_RAM 0 -// Some games have a built-in clock to keep track of time. -// This memory is usually just a couple of bytes to keep track of time. +/* Some games have a built-in clock to keep track of time. + * This memory is usually just a couple of bytes to keep track of time. + */ #define RETRO_MEMORY_RTC 1 -// System ram lets a frontend peek into a game systems main RAM. +/* System ram lets a frontend peek into a game systems main RAM. */ #define RETRO_MEMORY_SYSTEM_RAM 2 -// Video ram lets a frontend peek into a game systems video RAM (VRAM). +/* Video ram lets a frontend peek into a game systems video RAM (VRAM). */ #define RETRO_MEMORY_VIDEO_RAM 3 -// Special memory types. -#define RETRO_MEMORY_SNES_BSX_RAM ((1 << 8) | RETRO_MEMORY_SAVE_RAM) -#define RETRO_MEMORY_SNES_BSX_PRAM ((2 << 8) | RETRO_MEMORY_SAVE_RAM) -#define RETRO_MEMORY_SNES_SUFAMI_TURBO_A_RAM ((3 << 8) | RETRO_MEMORY_SAVE_RAM) -#define RETRO_MEMORY_SNES_SUFAMI_TURBO_B_RAM ((4 << 8) | RETRO_MEMORY_SAVE_RAM) -#define RETRO_MEMORY_SNES_GAME_BOY_RAM ((5 << 8) | RETRO_MEMORY_SAVE_RAM) -#define RETRO_MEMORY_SNES_GAME_BOY_RTC ((6 << 8) | RETRO_MEMORY_RTC) - -// Special game types passed into retro_load_game_special(). -// Only used when multiple ROMs are required. -#define RETRO_GAME_TYPE_BSX 0x101 -#define RETRO_GAME_TYPE_BSX_SLOTTED 0x102 -#define RETRO_GAME_TYPE_SUFAMI_TURBO 0x103 -#define RETRO_GAME_TYPE_SUPER_GAME_BOY 0x104 - -// Keysyms used for ID in input state callback when polling RETRO_KEYBOARD. +/* Keysyms used for ID in input state callback when polling RETRO_KEYBOARD. */ enum retro_key { RETROK_UNKNOWN = 0, @@ -344,7 +384,7 @@ enum retro_key RETROK_LAST, - RETROK_DUMMY = INT_MAX // Ensure sizeof(enum) == sizeof(int) + RETROK_DUMMY = INT_MAX /* Ensure sizeof(enum) == sizeof(int) */ }; enum retro_mod @@ -360,214 +400,692 @@ enum retro_mod RETROKMOD_CAPSLOCK = 0x20, RETROKMOD_SCROLLOCK = 0x40, - RETROKMOD_DUMMY = INT_MAX // Ensure sizeof(enum) == sizeof(int) + RETROKMOD_DUMMY = INT_MAX /* Ensure sizeof(enum) == sizeof(int) */ }; -// If set, this call is not part of the public libretro API yet. It can change or be removed at any time. +/* If set, this call is not part of the public libretro API yet. It can + * change or be removed at any time. */ #define RETRO_ENVIRONMENT_EXPERIMENTAL 0x10000 -// Environment callback to be used internally in frontend. +/* Environment callback to be used internally in frontend. */ #define RETRO_ENVIRONMENT_PRIVATE 0x20000 -// Environment commands. -#define RETRO_ENVIRONMENT_SET_ROTATION 1 // const unsigned * -- - // Sets screen rotation of graphics. - // Is only implemented if rotation can be accelerated by hardware. - // Valid values are 0, 1, 2, 3, which rotates screen by 0, 90, 180, 270 degrees - // counter-clockwise respectively. - // -#define RETRO_ENVIRONMENT_GET_OVERSCAN 2 // bool * -- - // Boolean value whether or not the implementation should use overscan, or crop away overscan. - // -#define RETRO_ENVIRONMENT_GET_CAN_DUPE 3 // bool * -- - // Boolean value whether or not frontend supports frame duping, - // passing NULL to video frame callback. - // -// Environ 4, 5 are no longer supported (GET_VARIABLE / SET_VARIABLES), and reserved to avoid possible ABI clash. -#define RETRO_ENVIRONMENT_SET_MESSAGE 6 // const struct retro_message * -- - // Sets a message to be displayed in implementation-specific manner for a certain amount of 'frames'. - // Should not be used for trivial messages, which should simply be logged to stderr. -#define RETRO_ENVIRONMENT_SHUTDOWN 7 // N/A (NULL) -- - // Requests the frontend to shutdown. - // Should only be used if game has a specific - // way to shutdown the game from a menu item or similar. - // +/* Environment commands. */ +#define RETRO_ENVIRONMENT_SET_ROTATION 1 /* const unsigned * -- + * Sets screen rotation of graphics. + * Is only implemented if rotation can be accelerated by hardware. + * Valid values are 0, 1, 2, 3, which rotates screen by 0, 90, 180, + * 270 degrees counter-clockwise respectively. + */ +#define RETRO_ENVIRONMENT_GET_OVERSCAN 2 /* bool * -- + * Boolean value whether or not the implementation should use overscan, + * or crop away overscan. + */ +#define RETRO_ENVIRONMENT_GET_CAN_DUPE 3 /* bool * -- + * Boolean value whether or not frontend supports frame duping, + * passing NULL to video frame callback. + */ + + /* Environ 4, 5 are no longer supported (GET_VARIABLE / SET_VARIABLES), + * and reserved to avoid possible ABI clash. + */ + +#define RETRO_ENVIRONMENT_SET_MESSAGE 6 /* const struct retro_message * -- + * Sets a message to be displayed in implementation-specific manner + * for a certain amount of 'frames'. + * Should not be used for trivial messages, which should simply be + * logged via RETRO_ENVIRONMENT_GET_LOG_INTERFACE (or as a + * fallback, stderr). + */ +#define RETRO_ENVIRONMENT_SHUTDOWN 7 /* N/A (NULL) -- + * Requests the frontend to shutdown. + * Should only be used if game has a specific + * way to shutdown the game from a menu item or similar. + */ #define RETRO_ENVIRONMENT_SET_PERFORMANCE_LEVEL 8 - // const unsigned * -- - // Gives a hint to the frontend how demanding this implementation - // is on a system. E.g. reporting a level of 2 means - // this implementation should run decently on all frontends - // of level 2 and up. - // - // It can be used by the frontend to potentially warn - // about too demanding implementations. - // - // The levels are "floating", but roughly defined as: - // 0: Low-powered embedded devices such as Raspberry Pi - // 1: 6th generation consoles, such as Wii/Xbox 1, and phones, tablets, etc. - // 2: 7th generation consoles, such as PS3/360, with sub-par CPUs. - // 3: Modern desktop/laptops with reasonably powerful CPUs. - // 4: High-end desktops with very powerful CPUs. - // - // This function can be called on a per-game basis, - // as certain games an implementation can play might be - // particularily demanding. - // If called, it should be called in retro_load_game(). - // + /* const unsigned * -- + * Gives a hint to the frontend how demanding this implementation + * is on a system. E.g. reporting a level of 2 means + * this implementation should run decently on all frontends + * of level 2 and up. + * + * It can be used by the frontend to potentially warn + * about too demanding implementations. + * + * The levels are "floating". + * + * This function can be called on a per-game basis, + * as certain games an implementation can play might be + * particularly demanding. + * If called, it should be called in retro_load_game(). + */ #define RETRO_ENVIRONMENT_GET_SYSTEM_DIRECTORY 9 - // const char ** -- - // Returns the "system" directory of the frontend. - // This directory can be used to store system specific ROMs such as BIOSes, configuration data, etc. - // The returned value can be NULL. - // If so, no such directory is defined, - // and it's up to the implementation to find a suitable directory. - // + /* const char ** -- + * Returns the "system" directory of the frontend. + * This directory can be used to store system specific + * content such as BIOSes, configuration data, etc. + * The returned value can be NULL. + * If so, no such directory is defined, + * and it's up to the implementation to find a suitable directory. + * + * NOTE: Some cores used this folder also for "save" data such as + * memory cards, etc, for lack of a better place to put it. + * This is now discouraged, and if possible, cores should try to + * use the new GET_SAVE_DIRECTORY. + */ #define RETRO_ENVIRONMENT_SET_PIXEL_FORMAT 10 - // const enum retro_pixel_format * -- - // Sets the internal pixel format used by the implementation. - // The default pixel format is RETRO_PIXEL_FORMAT_0RGB1555. - // This pixel format however, is deprecated (see enum retro_pixel_format). - // If the call returns false, the frontend does not support this pixel format. - // This function should be called inside retro_load_game() or retro_get_system_av_info(). - // + /* const enum retro_pixel_format * -- + * Sets the internal pixel format used by the implementation. + * The default pixel format is RETRO_PIXEL_FORMAT_0RGB1555. + * This pixel format however, is deprecated (see enum retro_pixel_format). + * If the call returns false, the frontend does not support this pixel + * format. + * + * This function should be called inside retro_load_game() or + * retro_get_system_av_info(). + */ #define RETRO_ENVIRONMENT_SET_INPUT_DESCRIPTORS 11 - // const struct retro_input_descriptor * -- - // Sets an array of retro_input_descriptors. - // It is up to the frontend to present this in a usable way. - // The array is terminated by retro_input_descriptor::description being set to NULL. - // This function can be called at any time, but it is recommended to call it as early as possible. + /* const struct retro_input_descriptor * -- + * Sets an array of retro_input_descriptors. + * It is up to the frontend to present this in a usable way. + * The array is terminated by retro_input_descriptor::description + * being set to NULL. + * This function can be called at any time, but it is recommended + * to call it as early as possible. + */ #define RETRO_ENVIRONMENT_SET_KEYBOARD_CALLBACK 12 - // const struct retro_keyboard_callback * -- - // Sets a callback function used to notify core about keyboard events. - // + /* const struct retro_keyboard_callback * -- + * Sets a callback function used to notify core about keyboard events. + */ #define RETRO_ENVIRONMENT_SET_DISK_CONTROL_INTERFACE 13 - // const struct retro_disk_control_callback * -- - // Sets an interface which frontend can use to eject and insert disk images. - // This is used for games which consist of multiple images and must be manually - // swapped out by the user (e.g. PSX). + /* const struct retro_disk_control_callback * -- + * Sets an interface which frontend can use to eject and insert + * disk images. + * This is used for games which consist of multiple images and + * must be manually swapped out by the user (e.g. PSX). + */ #define RETRO_ENVIRONMENT_SET_HW_RENDER 14 - // struct retro_hw_render_callback * -- - // Sets an interface to let a libretro core render with hardware acceleration. - // Should be called in retro_load_game(). - // If successful, libretro cores will be able to render to a frontend-provided framebuffer. - // The size of this framebuffer will be at least as large as max_width/max_height provided in get_av_info(). - // If HW rendering is used, pass only RETRO_HW_FRAME_BUFFER_VALID or NULL to retro_video_refresh_t. + /* struct retro_hw_render_callback * -- + * Sets an interface to let a libretro core render with + * hardware acceleration. + * Should be called in retro_load_game(). + * If successful, libretro cores will be able to render to a + * frontend-provided framebuffer. + * The size of this framebuffer will be at least as large as + * max_width/max_height provided in get_av_info(). + * If HW rendering is used, pass only RETRO_HW_FRAME_BUFFER_VALID or + * NULL to retro_video_refresh_t. + */ #define RETRO_ENVIRONMENT_GET_VARIABLE 15 - // struct retro_variable * -- - // Interface to acquire user-defined information from environment - // that cannot feasibly be supported in a multi-system way. - // 'key' should be set to a key which has already been set by SET_VARIABLES. - // 'data' will be set to a value or NULL. - // + /* struct retro_variable * -- + * Interface to acquire user-defined information from environment + * that cannot feasibly be supported in a multi-system way. + * 'key' should be set to a key which has already been set by + * SET_VARIABLES. + * 'data' will be set to a value or NULL. + */ #define RETRO_ENVIRONMENT_SET_VARIABLES 16 - // const struct retro_variable * -- - // Allows an implementation to signal the environment - // which variables it might want to check for later using GET_VARIABLE. - // This allows the frontend to present these variables to a user dynamically. - // This should be called as early as possible (ideally in retro_set_environment). - // - // 'data' points to an array of retro_variable structs terminated by a { NULL, NULL } element. - // retro_variable::key should be namespaced to not collide with other implementations' keys. E.g. A core called 'foo' should use keys named as 'foo_option'. - // retro_variable::value should contain a human readable description of the key as well as a '|' delimited list of expected values. - // The number of possible options should be very limited, i.e. it should be feasible to cycle through options without a keyboard. - // First entry should be treated as a default. - // - // Example entry: - // { "foo_option", "Speed hack coprocessor X; false|true" } - // - // Text before first ';' is description. This ';' must be followed by a space, and followed by a list of possible values split up with '|'. - // Only strings are operated on. The possible values will generally be displayed and stored as-is by the frontend. - // + /* const struct retro_variable * -- + * Allows an implementation to signal the environment + * which variables it might want to check for later using + * GET_VARIABLE. + * This allows the frontend to present these variables to + * a user dynamically. + * This should be called as early as possible (ideally in + * retro_set_environment). + * + * 'data' points to an array of retro_variable structs + * terminated by a { NULL, NULL } element. + * retro_variable::key should be namespaced to not collide + * with other implementations' keys. E.g. A core called + * 'foo' should use keys named as 'foo_option'. + * retro_variable::value should contain a human readable + * description of the key as well as a '|' delimited list + * of expected values. + * + * The number of possible options should be very limited, + * i.e. it should be feasible to cycle through options + * without a keyboard. + * + * First entry should be treated as a default. + * + * Example entry: + * { "foo_option", "Speed hack coprocessor X; false|true" } + * + * Text before first ';' is description. This ';' must be + * followed by a space, and followed by a list of possible + * values split up with '|'. + * + * Only strings are operated on. The possible values will + * generally be displayed and stored as-is by the frontend. + */ #define RETRO_ENVIRONMENT_GET_VARIABLE_UPDATE 17 - // bool * -- - // Result is set to true if some variables are updated by - // frontend since last call to RETRO_ENVIRONMENT_GET_VARIABLE. - // Variables should be queried with GET_VARIABLE. - // + /* bool * -- + * Result is set to true if some variables are updated by + * frontend since last call to RETRO_ENVIRONMENT_GET_VARIABLE. + * Variables should be queried with GET_VARIABLE. + */ #define RETRO_ENVIRONMENT_SET_SUPPORT_NO_GAME 18 - // const bool * -- - // If true, the libretro implementation supports calls to retro_load_game() with NULL as argument. - // Used by cores which can run without particular game data. - // This should be called within retro_set_environment() only. - // + /* const bool * -- + * If true, the libretro implementation supports calls to + * retro_load_game() with NULL as argument. + * Used by cores which can run without particular game data. + * This should be called within retro_set_environment() only. + */ #define RETRO_ENVIRONMENT_GET_LIBRETRO_PATH 19 - // const char ** -- - // Retrieves the absolute path from where this libretro implementation was loaded. - // NULL is returned if the libretro was loaded statically (i.e. linked statically to frontend), or if the path cannot be determined. - // Mostly useful in cooperation with SET_SUPPORT_NO_GAME as assets can be loaded without ugly hacks. - // - // -// Environment 20 was an obsolete version of SET_AUDIO_CALLBACK. It was not used by any known core at the time, -// and was removed from the API. + /* const char ** -- + * Retrieves the absolute path from where this libretro + * implementation was loaded. + * NULL is returned if the libretro was loaded statically + * (i.e. linked statically to frontend), or if the path cannot be + * determined. + * Mostly useful in cooperation with SET_SUPPORT_NO_GAME as assets can + * be loaded without ugly hacks. + */ + + /* Environment 20 was an obsolete version of SET_AUDIO_CALLBACK. + * It was not used by any known core at the time, + * and was removed from the API. */ #define RETRO_ENVIRONMENT_SET_AUDIO_CALLBACK 22 - // const struct retro_audio_callback * -- - // Sets an interface which is used to notify a libretro core about audio being available for writing. - // The callback can be called from any thread, so a core using this must have a thread safe audio implementation. - // It is intended for games where audio and video are completely asynchronous and audio can be generated on the fly. - // This interface is not recommended for use with emulators which have highly synchronous audio. - // - // The callback only notifies about writability; the libretro core still has to call the normal audio callbacks - // to write audio. The audio callbacks must be called from within the notification callback. - // The amount of audio data to write is up to the implementation. - // Generally, the audio callback will be called continously in a loop. - // - // Due to thread safety guarantees and lack of sync between audio and video, a frontend - // can selectively disallow this interface based on internal configuration. A core using - // this interface must also implement the "normal" audio interface. - // - // A libretro core using SET_AUDIO_CALLBACK should also make use of SET_FRAME_TIME_CALLBACK. + /* const struct retro_audio_callback * -- + * Sets an interface which is used to notify a libretro core about audio + * being available for writing. + * The callback can be called from any thread, so a core using this must + * have a thread safe audio implementation. + * It is intended for games where audio and video are completely + * asynchronous and audio can be generated on the fly. + * This interface is not recommended for use with emulators which have + * highly synchronous audio. + * + * The callback only notifies about writability; the libretro core still + * has to call the normal audio callbacks + * to write audio. The audio callbacks must be called from within the + * notification callback. + * The amount of audio data to write is up to the implementation. + * Generally, the audio callback will be called continously in a loop. + * + * Due to thread safety guarantees and lack of sync between audio and + * video, a frontend can selectively disallow this interface based on + * internal configuration. A core using this interface must also + * implement the "normal" audio interface. + * + * A libretro core using SET_AUDIO_CALLBACK should also make use of + * SET_FRAME_TIME_CALLBACK. + */ #define RETRO_ENVIRONMENT_SET_FRAME_TIME_CALLBACK 21 - // const struct retro_frame_time_callback * -- - // Lets the core know how much time has passed since last invocation of retro_run(). - // The frontend can tamper with the timing to fake fast-forward, slow-motion, frame stepping, etc. - // In this case the delta time will use the reference value in frame_time_callback.. - // + /* const struct retro_frame_time_callback * -- + * Lets the core know how much time has passed since last + * invocation of retro_run(). + * The frontend can tamper with the timing to fake fast-forward, + * slow-motion, frame stepping, etc. + * In this case the delta time will use the reference value + * in frame_time_callback.. + */ #define RETRO_ENVIRONMENT_GET_RUMBLE_INTERFACE 23 - // struct retro_rumble_interface * -- - // Gets an interface which is used by a libretro core to set state of rumble motors in controllers. - // A strong and weak motor is supported, and they can be controlled indepedently. - // + /* struct retro_rumble_interface * -- + * Gets an interface which is used by a libretro core to set + * state of rumble motors in controllers. + * A strong and weak motor is supported, and they can be + * controlled indepedently. + */ #define RETRO_ENVIRONMENT_GET_INPUT_DEVICE_CAPABILITIES 24 - // uint64_t * -- - // Gets a bitmask telling which device type are expected to be handled properly in a call to retro_input_state_t. - // Devices which are not handled or recognized always return 0 in retro_input_state_t. - // Example bitmask: caps = (1 << RETRO_DEVICE_JOYPAD) | (1 << RETRO_DEVICE_ANALOG). - // Should only be called in retro_run(). - // + /* uint64_t * -- + * Gets a bitmask telling which device type are expected to be + * handled properly in a call to retro_input_state_t. + * Devices which are not handled or recognized always return + * 0 in retro_input_state_t. + * Example bitmask: caps = (1 << RETRO_DEVICE_JOYPAD) | (1 << RETRO_DEVICE_ANALOG). + * Should only be called in retro_run(). + */ #define RETRO_ENVIRONMENT_GET_SENSOR_INTERFACE (25 | RETRO_ENVIRONMENT_EXPERIMENTAL) - // struct retro_sensor_interface * -- - // Gets access to the sensor interface. - // The purpose of this interface is to allow - // setting state related to sensors such as polling rate, enabling/disable it entirely, etc. - // Reading sensor state is done via the normal input_state_callback API. - // + /* struct retro_sensor_interface * -- + * Gets access to the sensor interface. + * The purpose of this interface is to allow + * setting state related to sensors such as polling rate, + * enabling/disable it entirely, etc. + * Reading sensor state is done via the normal + * input_state_callback API. + */ #define RETRO_ENVIRONMENT_GET_CAMERA_INTERFACE (26 | RETRO_ENVIRONMENT_EXPERIMENTAL) - // struct retro_camera_callback * -- - // Gets an interface to a video camera driver. - // A libretro core can use this interface to get access to a video camera. - // New video frames are delivered in a callback in same thread as retro_run(). - // - // GET_CAMERA_INTERFACE should be called in retro_load_game(). - // - // Depending on the camera implementation used, camera frames will be delivered as a raw framebuffer, - // or as an OpenGL texture directly. - // - // The core has to tell the frontend here which types of buffers can be handled properly. - // An OpenGL texture can only be handled when using a libretro GL core (SET_HW_RENDER). - // It is recommended to use a libretro GL core when using camera interface. - // - // The camera is not started automatically. The retrieved start/stop functions must be used to explicitly - // start and stop the camera driver. - // + /* struct retro_camera_callback * -- + * Gets an interface to a video camera driver. + * A libretro core can use this interface to get access to a + * video camera. + * New video frames are delivered in a callback in same + * thread as retro_run(). + * + * GET_CAMERA_INTERFACE should be called in retro_load_game(). + * + * Depending on the camera implementation used, camera frames + * will be delivered as a raw framebuffer, + * or as an OpenGL texture directly. + * + * The core has to tell the frontend here which types of + * buffers can be handled properly. + * An OpenGL texture can only be handled when using a + * libretro GL core (SET_HW_RENDER). + * It is recommended to use a libretro GL core when + * using camera interface. + * + * The camera is not started automatically. The retrieved start/stop + * functions must be used to explicitly + * start and stop the camera driver. + */ #define RETRO_ENVIRONMENT_GET_LOG_INTERFACE 27 - // struct retro_log_callback * -- - // Gets an interface for logging. This is useful for logging in a cross-platform way - // as certain platforms cannot use use stderr for logging. It also allows the frontend to - // show logging information in a more suitable way. - // If this interface is not used, libretro cores should log to stderr as desired. + /* struct retro_log_callback * -- + * Gets an interface for logging. This is useful for + * logging in a cross-platform way + * as certain platforms cannot use use stderr for logging. + * It also allows the frontend to + * show logging information in a more suitable way. + * If this interface is not used, libretro cores should + * log to stderr as desired. + */ #define RETRO_ENVIRONMENT_GET_PERF_INTERFACE 28 - // struct retro_perf_callback * -- - // Gets an interface for performance counters. This is useful for performance logging in a - // cross-platform way and for detecting architecture-specific features, such as SIMD support. + /* struct retro_perf_callback * -- + * Gets an interface for performance counters. This is useful + * for performance logging in a cross-platform way and for detecting + * architecture-specific features, such as SIMD support. + */ +#define RETRO_ENVIRONMENT_GET_LOCATION_INTERFACE 29 + /* struct retro_location_callback * -- + * Gets access to the location interface. + * The purpose of this interface is to be able to retrieve + * location-based information from the host device, + * such as current latitude / longitude. + */ +#define RETRO_ENVIRONMENT_GET_CONTENT_DIRECTORY 30 + /* const char ** -- + * Returns the "content" directory of the frontend. + * This directory can be used to store specific assets that the + * core relies upon, such as art assets, + * input data, etc etc. + * The returned value can be NULL. + * If so, no such directory is defined, + * and it's up to the implementation to find a suitable directory. + */ +#define RETRO_ENVIRONMENT_GET_SAVE_DIRECTORY 31 + /* const char ** -- + * Returns the "save" directory of the frontend. + * This directory can be used to store SRAM, memory cards, + * high scores, etc, if the libretro core + * cannot use the regular memory interface (retro_get_memory_data()). + * + * NOTE: libretro cores used to check GET_SYSTEM_DIRECTORY for + * similar things before. + * They should still check GET_SYSTEM_DIRECTORY if they want to + * be backwards compatible. + * The path here can be NULL. It should only be non-NULL if the + * frontend user has set a specific save path. + */ +#define RETRO_ENVIRONMENT_SET_SYSTEM_AV_INFO 32 + /* const struct retro_system_av_info * -- + * Sets a new av_info structure. This can only be called from + * within retro_run(). + * This should *only* be used if the core is completely altering the + * internal resolutions, aspect ratios, timings, sampling rate, etc. + * Calling this can require a full reinitialization of video/audio + * drivers in the frontend, + * + * so it is important to call it very sparingly, and usually only with + * the users explicit consent. + * An eventual driver reinitialize will happen so that video and + * audio callbacks + * happening after this call within the same retro_run() call will + * target the newly initialized driver. + * + * This callback makes it possible to support configurable resolutions + * in games, which can be useful to + * avoid setting the "worst case" in max_width/max_height. + * + * ***HIGHLY RECOMMENDED*** Do not call this callback every time + * resolution changes in an emulator core if it's + * expected to be a temporary change, for the reasons of possible + * driver reinitialization. + * This call is not a free pass for not trying to provide + * correct values in retro_get_system_av_info(). If you need to change + * things like aspect ratio or nominal width/height, + * use RETRO_ENVIRONMENT_SET_GEOMETRY, which is a softer variant + * of SET_SYSTEM_AV_INFO. + * + * If this returns false, the frontend does not acknowledge a + * changed av_info struct. + */ +#define RETRO_ENVIRONMENT_SET_PROC_ADDRESS_CALLBACK 33 + /* const struct retro_get_proc_address_interface * -- + * Allows a libretro core to announce support for the + * get_proc_address() interface. + * This interface allows for a standard way to extend libretro where + * use of environment calls are too indirect, + * e.g. for cases where the frontend wants to call directly into the core. + * + * If a core wants to expose this interface, SET_PROC_ADDRESS_CALLBACK + * **MUST** be called from within retro_set_environment(). + */ +#define RETRO_ENVIRONMENT_SET_SUBSYSTEM_INFO 34 + /* const struct retro_subsystem_info * -- + * This environment call introduces the concept of libretro "subsystems". + * A subsystem is a variant of a libretro core which supports + * different kinds of games. + * The purpose of this is to support e.g. emulators which might + * have special needs, e.g. Super Nintendo's Super GameBoy, Sufami Turbo. + * It can also be used to pick among subsystems in an explicit way + * if the libretro implementation is a multi-system emulator itself. + * + * Loading a game via a subsystem is done with retro_load_game_special(), + * and this environment call allows a libretro core to expose which + * subsystems are supported for use with retro_load_game_special(). + * A core passes an array of retro_game_special_info which is terminated + * with a zeroed out retro_game_special_info struct. + * + * If a core wants to use this functionality, SET_SUBSYSTEM_INFO + * **MUST** be called from within retro_set_environment(). + */ +#define RETRO_ENVIRONMENT_SET_CONTROLLER_INFO 35 + /* const struct retro_controller_info * -- + * This environment call lets a libretro core tell the frontend + * which controller types are recognized in calls to + * retro_set_controller_port_device(). + * + * Some emulators such as Super Nintendo + * support multiple lightgun types which must be specifically + * selected from. + * It is therefore sometimes necessary for a frontend to be able + * to tell the core about a special kind of input device which is + * not covered by the libretro input API. + * + * In order for a frontend to understand the workings of an input device, + * it must be a specialized type + * of the generic device types already defined in the libretro API. + * + * Which devices are supported can vary per input port. + * The core must pass an array of const struct retro_controller_info which + * is terminated with a blanked out struct. Each element of the struct + * corresponds to an ascending port index to + * retro_set_controller_port_device(). + * Even if special device types are set in the libretro core, + * libretro should only poll input based on the base input device types. + */ +#define RETRO_ENVIRONMENT_SET_MEMORY_MAPS (36 | RETRO_ENVIRONMENT_EXPERIMENTAL) + /* const struct retro_memory_map * -- + * This environment call lets a libretro core tell the frontend + * about the memory maps this core emulates. + * This can be used to implement, for example, cheats in a core-agnostic way. + * + * Should only be used by emulators; it doesn't make much sense for + * anything else. + * It is recommended to expose all relevant pointers through + * retro_get_memory_* as well. + * + * Can be called from retro_init and retro_load_game. + */ +#define RETRO_ENVIRONMENT_SET_GEOMETRY 37 + /* const struct retro_game_geometry * -- + * This environment call is similar to SET_SYSTEM_AV_INFO for changing + * video parameters, but provides a guarantee that drivers will not be + * reinitialized. + * This can only be called from within retro_run(). + * + * The purpose of this call is to allow a core to alter nominal + * width/heights as well as aspect ratios on-the-fly, which can be + * useful for some emulators to change in run-time. + * + * max_width/max_height arguments are ignored and cannot be changed + * with this call as this could potentially require a reinitialization or a + * non-constant time operation. + * If max_width/max_height are to be changed, SET_SYSTEM_AV_INFO is required. + * + * A frontend must guarantee that this environment call completes in + * constant time. + */ +#define RETRO_ENVIRONMENT_GET_USERNAME 38 + /* const char ** + * Returns the specified username of the frontend, if specified by the user. + * This username can be used as a nickname for a core that has online facilities + * or any other mode where personalization of the user is desirable. + * The returned value can be NULL. + * If this environ callback is used by a core that requires a valid username, + * a default username should be specified by the core. + */ +#define RETRO_ENVIRONMENT_GET_LANGUAGE 39 + /* unsigned * -- + * Returns the specified language of the frontend, if specified by the user. + * It can be used by the core for localization purposes. + */ + +#define RETRO_MEMDESC_CONST (1 << 0) /* The frontend will never change this memory area once retro_load_game has returned. */ +#define RETRO_MEMDESC_BIGENDIAN (1 << 1) /* The memory area contains big endian data. Default is little endian. */ +#define RETRO_MEMDESC_ALIGN_2 (1 << 16) /* All memory access in this area is aligned to their own size, or 2, whichever is smaller. */ +#define RETRO_MEMDESC_ALIGN_4 (2 << 16) +#define RETRO_MEMDESC_ALIGN_8 (3 << 16) +#define RETRO_MEMDESC_MINSIZE_2 (1 << 24) /* All memory in this region is accessed at least 2 bytes at the time. */ +#define RETRO_MEMDESC_MINSIZE_4 (2 << 24) +#define RETRO_MEMDESC_MINSIZE_8 (3 << 24) +struct retro_memory_descriptor +{ + uint64_t flags; + + /* Pointer to the start of the relevant ROM or RAM chip. + * It's strongly recommended to use 'offset' if possible, rather than + * doing math on the pointer. + * + * If the same byte is mapped my multiple descriptors, their descriptors + * must have the same pointer. + * If 'start' does not point to the first byte in the pointer, put the + * difference in 'offset' instead. + * + * May be NULL if there's nothing usable here (e.g. hardware registers and + * open bus). No flags should be set if the pointer is NULL. + * It's recommended to minimize the number of descriptors if possible, + * but not mandatory. */ + void *ptr; + size_t offset; + + /* This is the location in the emulated address space + * where the mapping starts. */ + size_t start; + + /* Which bits must be same as in 'start' for this mapping to apply. + * The first memory descriptor to claim a certain byte is the one + * that applies. + * A bit which is set in 'start' must also be set in this. + * Can be zero, in which case each byte is assumed mapped exactly once. + * In this case, 'len' must be a power of two. */ + size_t select; + + /* If this is nonzero, the set bits are assumed not connected to the + * memory chip's address pins. */ + size_t disconnect; + + /* This one tells the size of the current memory area. + * If, after start+disconnect are applied, the address is higher than + * this, the highest bit of the address is cleared. + * + * If the address is still too high, the next highest bit is cleared. + * Can be zero, in which case it's assumed to be infinite (as limited + * by 'select' and 'disconnect'). */ + size_t len; + + /* To go from emulated address to physical address, the following + * order applies: + * Subtract 'start', pick off 'disconnect', apply 'len', add 'offset'. + * + * The address space name must consist of only a-zA-Z0-9_-, + * should be as short as feasible (maximum length is 8 plus the NUL), + * and may not be any other address space plus one or more 0-9A-F + * at the end. + * However, multiple memory descriptors for the same address space is + * allowed, and the address space name can be empty. NULL is treated + * as empty. + * + * Address space names are case sensitive, but avoid lowercase if possible. + * The same pointer may exist in multiple address spaces. + * + * Examples: + * blank+blank - valid (multiple things may be mapped in the same namespace) + * 'Sp'+'Sp' - valid (multiple things may be mapped in the same namespace) + * 'A'+'B' - valid (neither is a prefix of each other) + * 'S'+blank - valid ('S' is not in 0-9A-F) + * 'a'+blank - valid ('a' is not in 0-9A-F) + * 'a'+'A' - valid (neither is a prefix of each other) + * 'AR'+blank - valid ('R' is not in 0-9A-F) + * 'ARB'+blank - valid (the B can't be part of the address either, because + * there is no namespace 'AR') + * blank+'B' - not valid, because it's ambigous which address space B1234 + * would refer to. + * The length can't be used for that purpose; the frontend may want + * to append arbitrary data to an address, without a separator. */ + const char *addrspace; +}; + +/* The frontend may use the largest value of 'start'+'select' in a + * certain namespace to infer the size of the address space. + * + * If the address space is larger than that, a mapping with .ptr=NULL + * should be at the end of the array, with .select set to all ones for + * as long as the address space is big. + * + * Sample descriptors (minus .ptr, and RETRO_MEMFLAG_ on the flags): + * SNES WRAM: + * .start=0x7E0000, .len=0x20000 + * (Note that this must be mapped before the ROM in most cases; some of the + * ROM mappers + * try to claim $7E0000, or at least $7E8000.) + * SNES SPC700 RAM: + * .addrspace="S", .len=0x10000 + * SNES WRAM mirrors: + * .flags=MIRROR, .start=0x000000, .select=0xC0E000, .len=0x2000 + * .flags=MIRROR, .start=0x800000, .select=0xC0E000, .len=0x2000 + * SNES WRAM mirrors, alternate equivalent descriptor: + * .flags=MIRROR, .select=0x40E000, .disconnect=~0x1FFF + * (Various similar constructions can be created by combining parts of + * the above two.) + * SNES LoROM (512KB, mirrored a couple of times): + * .flags=CONST, .start=0x008000, .select=0x408000, .disconnect=0x8000, .len=512*1024 + * .flags=CONST, .start=0x400000, .select=0x400000, .disconnect=0x8000, .len=512*1024 + * SNES HiROM (4MB): + * .flags=CONST, .start=0x400000, .select=0x400000, .len=4*1024*1024 + * .flags=CONST, .offset=0x8000, .start=0x008000, .select=0x408000, .len=4*1024*1024 + * SNES ExHiROM (8MB): + * .flags=CONST, .offset=0, .start=0xC00000, .select=0xC00000, .len=4*1024*1024 + * .flags=CONST, .offset=4*1024*1024, .start=0x400000, .select=0xC00000, .len=4*1024*1024 + * .flags=CONST, .offset=0x8000, .start=0x808000, .select=0xC08000, .len=4*1024*1024 + * .flags=CONST, .offset=4*1024*1024+0x8000, .start=0x008000, .select=0xC08000, .len=4*1024*1024 + * Clarify the size of the address space: + * .ptr=NULL, .select=0xFFFFFF + * .len can be implied by .select in many of them, but was included for clarity. + */ + +struct retro_memory_map +{ + const struct retro_memory_descriptor *descriptors; + unsigned num_descriptors; +}; + +struct retro_controller_description +{ + /* Human-readable description of the controller. Even if using a generic + * input device type, this can be set to the particular device type the + * core uses. */ + const char *desc; + + /* Device type passed to retro_set_controller_port_device(). If the device + * type is a sub-class of a generic input device type, use the + * RETRO_DEVICE_SUBCLASS macro to create an ID. + * + * E.g. RETRO_DEVICE_SUBCLASS(RETRO_DEVICE_JOYPAD, 1). */ + unsigned id; +}; + +struct retro_controller_info +{ + const struct retro_controller_description *types; + unsigned num_types; +}; + +struct retro_subsystem_memory_info +{ + /* The extension associated with a memory type, e.g. "psram". */ + const char *extension; + + /* The memory type for retro_get_memory(). This should be at + * least 0x100 to avoid conflict with standardized + * libretro memory types. */ + unsigned type; +}; + +struct retro_subsystem_rom_info +{ + /* Describes what the content is (SGB BIOS, GB ROM, etc). */ + const char *desc; + + /* Same definition as retro_get_system_info(). */ + const char *valid_extensions; + + /* Same definition as retro_get_system_info(). */ + bool need_fullpath; + + /* Same definition as retro_get_system_info(). */ + bool block_extract; + + /* This is set if the content is required to load a game. + * If this is set to false, a zeroed-out retro_game_info can be passed. */ + bool required; + + /* Content can have multiple associated persistent + * memory types (retro_get_memory()). */ + const struct retro_subsystem_memory_info *memory; + unsigned num_memory; +}; + +struct retro_subsystem_info +{ + /* Human-readable string of the subsystem type, e.g. "Super GameBoy" */ + const char *desc; + + /* A computer friendly short string identifier for the subsystem type. + * This name must be [a-z]. + * E.g. if desc is "Super GameBoy", this can be "sgb". + * This identifier can be used for command-line interfaces, etc. + */ + const char *ident; + + /* Infos for each content file. The first entry is assumed to be the + * "most significant" content for frontend purposes. + * E.g. with Super GameBoy, the first content should be the GameBoy ROM, + * as it is the most "significant" content to a user. + * If a frontend creates new file paths based on the content used + * (e.g. savestates), it should use the path for the first ROM to do so. */ + const struct retro_subsystem_rom_info *roms; + + /* Number of content files associated with a subsystem. */ + unsigned num_roms; + + /* The type passed to retro_load_game_special(). */ + unsigned id; +}; + +typedef void (*retro_proc_address_t)(void); + +/* libretro API extension functions: + * (None here so far). + * + * Get a symbol from a libretro core. + * Cores should only return symbols which are actual + * extensions to the libretro API. + * + * Frontends should not use this to obtain symbols to standard + * libretro entry points (static linking or dlsym). + * + * The symbol name must be equal to the function name, + * e.g. if void retro_foo(void); exists, the symbol must be called "retro_foo". + * The returned function pointer must be cast to the corresponding type. + */ +typedef retro_proc_address_t (*retro_get_proc_address_t)(const char *sym); + +struct retro_get_proc_address_interface +{ + retro_get_proc_address_t get_proc_address; +}; enum retro_log_level { @@ -579,17 +1097,18 @@ enum retro_log_level RETRO_LOG_DUMMY = INT_MAX }; -// Logging function. Takes log level argument as well. -typedef void (*retro_log_printf_t)(enum retro_log_level level, const char *fmt, ...); +/* Logging function. Takes log level argument as well. */ +typedef void (*retro_log_printf_t)(enum retro_log_level level, + const char *fmt, ...); struct retro_log_callback { retro_log_printf_t log; }; -// Performance related functions -// -// ID values for SIMD CPU features +/* Performance related functions */ + +/* ID values for SIMD CPU features */ #define RETRO_SIMD_SSE (1 << 0) #define RETRO_SIMD_SSE2 (1 << 1) #define RETRO_SIMD_VMX (1 << 2) @@ -598,6 +1117,14 @@ struct retro_log_callback #define RETRO_SIMD_NEON (1 << 5) #define RETRO_SIMD_SSE3 (1 << 6) #define RETRO_SIMD_SSSE3 (1 << 7) +#define RETRO_SIMD_MMX (1 << 8) +#define RETRO_SIMD_MMXEXT (1 << 9) +#define RETRO_SIMD_SSE4 (1 << 10) +#define RETRO_SIMD_SSE42 (1 << 11) +#define RETRO_SIMD_AVX2 (1 << 12) +#define RETRO_SIMD_VFPU (1 << 13) +#define RETRO_SIMD_PS (1 << 14) +#define RETRO_SIMD_AES (1 << 15) typedef uint64_t retro_perf_tick_t; typedef int64_t retro_time_t; @@ -612,54 +1139,70 @@ struct retro_perf_counter bool registered; }; -// Returns current time in microseconds. Tries to use the most accurate timer available. +/* Returns current time in microseconds. + * Tries to use the most accurate timer available. + */ typedef retro_time_t (*retro_perf_get_time_usec_t)(void); -// A simple counter. Usually nanoseconds, but can also be CPU cycles. -// Can be used directly if desired (when creating a more sophisticated performance counter system). + +/* A simple counter. Usually nanoseconds, but can also be CPU cycles. + * Can be used directly if desired (when creating a more sophisticated + * performance counter system). + * */ typedef retro_perf_tick_t (*retro_perf_get_counter_t)(void); -// Returns a bit-mask of detected CPU features (RETRO_SIMD_*). + +/* Returns a bit-mask of detected CPU features (RETRO_SIMD_*). */ typedef uint64_t (*retro_get_cpu_features_t)(void); -// Asks frontend to log and/or display the state of performance counters. -// Performance counters can always be poked into manually as well. + +/* Asks frontend to log and/or display the state of performance counters. + * Performance counters can always be poked into manually as well. + */ typedef void (*retro_perf_log_t)(void); -// Register a performance counter. -// ident field must be set with a discrete value and other values in retro_perf_counter must be 0. -// Registering can be called multiple times. To avoid calling to frontend redundantly, you can check registered field first. + +/* Register a performance counter. + * ident field must be set with a discrete value and other values in + * retro_perf_counter must be 0. + * Registering can be called multiple times. To avoid calling to + * frontend redundantly, you can check registered field first. */ typedef void (*retro_perf_register_t)(struct retro_perf_counter *counter); -// Starts and stops a registered counter. + +/* Starts a registered counter. */ typedef void (*retro_perf_start_t)(struct retro_perf_counter *counter); + +/* Stops a registered counter. */ typedef void (*retro_perf_stop_t)(struct retro_perf_counter *counter); -// For convenience it can be useful to wrap register, start and stop in macros. -// E.g.: -// #ifdef LOG_PERFORMANCE -// #define RETRO_PERFORMANCE_INIT(perf_cb, name) static struct retro_perf_counter name = {#name}; if (!name.registered) perf_cb.perf_register(&(name)) -// #define RETRO_PERFORMANCE_START(perf_cb, name) perf_cb.perf_start(&(name)) -// #define RETRO_PERFORMANCE_STOP(perf_cb, name) perf_cb.perf_stop(&(name)) -// #else -// ... Blank macros ... -// #endif -// These can then be used mid-functions around code snippets. -// -// extern struct retro_perf_callback perf_cb; // Somewhere in the core. -// -// void do_some_heavy_work(void) -// { -// RETRO_PERFORMANCE_INIT(cb, work_1); -// RETRO_PERFORMANCE_START(cb, work_1); -// heavy_work_1(); -// RETRO_PERFORMANCE_STOP(cb, work_1); -// -// RETRO_PERFORMANCE_INIT(cb, work_2); -// RETRO_PERFORMANCE_START(cb, work_2); -// heavy_work_2(); -// RETRO_PERFORMANCE_STOP(cb, work_2); -// } -// -// void retro_deinit(void) -// { -// perf_cb.perf_log(); // Log all perf counters here for example. -// } +/* For convenience it can be useful to wrap register, start and stop in macros. + * E.g.: + * #ifdef LOG_PERFORMANCE + * #define RETRO_PERFORMANCE_INIT(perf_cb, name) static struct retro_perf_counter name = {#name}; if (!name.registered) perf_cb.perf_register(&(name)) + * #define RETRO_PERFORMANCE_START(perf_cb, name) perf_cb.perf_start(&(name)) + * #define RETRO_PERFORMANCE_STOP(perf_cb, name) perf_cb.perf_stop(&(name)) + * #else + * ... Blank macros ... + * #endif + * + * These can then be used mid-functions around code snippets. + * + * extern struct retro_perf_callback perf_cb; * Somewhere in the core. + * + * void do_some_heavy_work(void) + * { + * RETRO_PERFORMANCE_INIT(cb, work_1; + * RETRO_PERFORMANCE_START(cb, work_1); + * heavy_work_1(); + * RETRO_PERFORMANCE_STOP(cb, work_1); + * + * RETRO_PERFORMANCE_INIT(cb, work_2); + * RETRO_PERFORMANCE_START(cb, work_2); + * heavy_work_2(); + * RETRO_PERFORMANCE_STOP(cb, work_2); + * } + * + * void retro_deinit(void) + * { + * perf_cb.perf_log(); * Log all perf counters here for example. + * } + */ struct retro_perf_callback { @@ -673,8 +1216,9 @@ struct retro_perf_callback retro_perf_log_t perf_log; }; -// FIXME: Document the sensor API and work out behavior. -// It will be marked as experimental until then. +/* FIXME: Document the sensor API and work out behavior. + * It will be marked as experimental until then. + */ enum retro_sensor_action { RETRO_SENSOR_ACCELEROMETER_ENABLE = 0, @@ -683,12 +1227,21 @@ enum retro_sensor_action RETRO_SENSOR_DUMMY = INT_MAX }; -typedef bool (*retro_set_sensor_state_t)(unsigned port, enum retro_sensor_action action, unsigned rate); +/* Id values for SENSOR types. */ +#define RETRO_SENSOR_ACCELEROMETER_X 0 +#define RETRO_SENSOR_ACCELEROMETER_Y 1 +#define RETRO_SENSOR_ACCELEROMETER_Z 2 + +typedef bool (*retro_set_sensor_state_t)(unsigned port, + enum retro_sensor_action action, unsigned rate); + +typedef float (*retro_sensor_get_input_t)(unsigned port, unsigned id); + struct retro_sensor_interface { retro_set_sensor_state_t set_sensor_state; + retro_sensor_get_input_t get_sensor_input; }; -//// enum retro_camera_buffer { @@ -698,51 +1251,119 @@ enum retro_camera_buffer RETRO_CAMERA_BUFFER_DUMMY = INT_MAX }; -// Starts the camera driver. Can only be called in retro_run(). +/* Starts the camera driver. Can only be called in retro_run(). */ typedef bool (*retro_camera_start_t)(void); -// Stops the camera driver. Can only be called in retro_run(). + +/* Stops the camera driver. Can only be called in retro_run(). */ typedef void (*retro_camera_stop_t)(void); -// Callback which signals when the camera driver is initialized and/or deinitialized. -// retro_camera_start_t can be called in initialized callback. + +/* Callback which signals when the camera driver is initialized + * and/or deinitialized. + * retro_camera_start_t can be called in initialized callback. + */ typedef void (*retro_camera_lifetime_status_t)(void); -// A callback for raw framebuffer data. buffer points to an XRGB8888 buffer. -// Width, height and pitch are similar to retro_video_refresh_t. -// First pixel is top-left origin. -typedef void (*retro_camera_frame_raw_framebuffer_t)(const uint32_t *buffer, unsigned width, unsigned height, size_t pitch); -// A callback for when OpenGL textures are used. -// -// texture_id is a texture owned by camera driver. -// Its state or content should be considered immutable, except for things like texture filtering and clamping. -// -// texture_target is the texture target for the GL texture. -// These can include e.g. GL_TEXTURE_2D, GL_TEXTURE_RECTANGLE, and possibly more depending on extensions. -// -// affine points to a packed 3x3 column-major matrix used to apply an affine transform to texture coordinates. (affine_matrix * vec3(coord_x, coord_y, 1.0)) -// After transform, normalized texture coord (0, 0) should be bottom-left and (1, 1) should be top-right (or (width, height) for RECTANGLE). -// -// GL-specific typedefs are avoided here to avoid relying on gl.h in the API definition. -typedef void (*retro_camera_frame_opengl_texture_t)(unsigned texture_id, unsigned texture_target, const float *affine); + +/* A callback for raw framebuffer data. buffer points to an XRGB8888 buffer. + * Width, height and pitch are similar to retro_video_refresh_t. + * First pixel is top-left origin. + */ +typedef void (*retro_camera_frame_raw_framebuffer_t)(const uint32_t *buffer, + unsigned width, unsigned height, size_t pitch); + +/* A callback for when OpenGL textures are used. + * + * texture_id is a texture owned by camera driver. + * Its state or content should be considered immutable, except for things like + * texture filtering and clamping. + * + * texture_target is the texture target for the GL texture. + * These can include e.g. GL_TEXTURE_2D, GL_TEXTURE_RECTANGLE, and possibly + * more depending on extensions. + * + * affine points to a packed 3x3 column-major matrix used to apply an affine + * transform to texture coordinates. (affine_matrix * vec3(coord_x, coord_y, 1.0)) + * After transform, normalized texture coord (0, 0) should be bottom-left + * and (1, 1) should be top-right (or (width, height) for RECTANGLE). + * + * GL-specific typedefs are avoided here to avoid relying on gl.h in + * the API definition. + */ +typedef void (*retro_camera_frame_opengl_texture_t)(unsigned texture_id, + unsigned texture_target, const float *affine); + struct retro_camera_callback { - uint64_t caps; // Set by libretro core. Example bitmask: caps = (1 << RETRO_CAMERA_BUFFER_OPENGL_TEXTURE) | (1 << RETRO_CAMERA_BUFFER_RAW_FRAMEBUFFER). + /* Set by libretro core. + * Example bitmask: caps = (1 << RETRO_CAMERA_BUFFER_OPENGL_TEXTURE) | (1 << RETRO_CAMERA_BUFFER_RAW_FRAMEBUFFER). + */ + uint64_t caps; - unsigned width; // Desired resolution for camera. Is only used as a hint. + unsigned width; /* Desired resolution for camera. Is only used as a hint. */ unsigned height; - retro_camera_start_t start; // Set by frontend. - retro_camera_stop_t stop; // Set by frontend. - - retro_camera_frame_raw_framebuffer_t frame_raw_framebuffer; // Set by libretro core if raw framebuffer callbacks will be used. - retro_camera_frame_opengl_texture_t frame_opengl_texture; // Set by libretro core if OpenGL texture callbacks will be used. - - // Set by libretro core. Called after camera driver is initialized and ready to be started. - // Can be NULL, in which this callback is not called. + retro_camera_start_t start; /* Set by frontend. */ + retro_camera_stop_t stop; /* Set by frontend. */ + + /* Set by libretro core if raw framebuffer callbacks will be used. */ + retro_camera_frame_raw_framebuffer_t frame_raw_framebuffer; + /* Set by libretro core if OpenGL texture callbacks will be used. */ + retro_camera_frame_opengl_texture_t frame_opengl_texture; + + /* Set by libretro core. Called after camera driver is initialized and + * ready to be started. + * Can be NULL, in which this callback is not called. + */ retro_camera_lifetime_status_t initialized; - // Set by libretro core. Called right before camera driver is deinitialized. - // Can be NULL, in which this callback is not called. + /* Set by libretro core. Called right before camera driver is + * deinitialized. + * Can be NULL, in which this callback is not called. + */ retro_camera_lifetime_status_t deinitialized; }; +/* Sets the interval of time and/or distance at which to update/poll + * location-based data. + * + * To ensure compatibility with all location-based implementations, + * values for both interval_ms and interval_distance should be provided. + * + * interval_ms is the interval expressed in milliseconds. + * interval_distance is the distance interval expressed in meters. + */ +typedef void (*retro_location_set_interval_t)(unsigned interval_ms, + unsigned interval_distance); + +/* Start location services. The device will start listening for changes to the + * current location at regular intervals (which are defined with + * retro_location_set_interval_t). */ +typedef bool (*retro_location_start_t)(void); + +/* Stop location services. The device will stop listening for changes + * to the current location. */ +typedef void (*retro_location_stop_t)(void); + +/* Get the position of the current location. Will set parameters to + * 0 if no new location update has happened since the last time. */ +typedef bool (*retro_location_get_position_t)(double *lat, double *lon, + double *horiz_accuracy, double *vert_accuracy); + +/* Callback which signals when the location driver is initialized + * and/or deinitialized. + * retro_location_start_t can be called in initialized callback. + */ +typedef void (*retro_location_lifetime_status_t)(void); + +struct retro_location_callback +{ + retro_location_start_t start; + retro_location_stop_t stop; + retro_location_get_position_t get_position; + retro_location_set_interval_t set_interval; + + retro_location_lifetime_status_t initialized; + retro_location_lifetime_status_t deinitialized; +}; + enum retro_rumble_effect { RETRO_RUMBLE_STRONG = 0, @@ -751,145 +1372,260 @@ enum retro_rumble_effect RETRO_RUMBLE_DUMMY = INT_MAX }; -// Sets rumble state for joypad plugged in port 'port'. Rumble effects are controlled independently, -// and setting e.g. strong rumble does not override weak rumble. -// Strength has a range of [0, 0xffff]. -// -// Returns true if rumble state request was honored. Calling this before first retro_run() is likely to return false. -typedef bool (*retro_set_rumble_state_t)(unsigned port, enum retro_rumble_effect effect, uint16_t strength); +/* Sets rumble state for joypad plugged in port 'port'. + * Rumble effects are controlled independently, + * and setting e.g. strong rumble does not override weak rumble. + * Strength has a range of [0, 0xffff]. + * + * Returns true if rumble state request was honored. + * Calling this before first retro_run() is likely to return false. */ +typedef bool (*retro_set_rumble_state_t)(unsigned port, + enum retro_rumble_effect effect, uint16_t strength); + struct retro_rumble_interface { retro_set_rumble_state_t set_rumble_state; }; -// Notifies libretro that audio data should be written. +/* Notifies libretro that audio data should be written. */ typedef void (*retro_audio_callback_t)(void); -// True: Audio driver in frontend is active, and callback is expected to be called regularily. -// False: Audio driver in frontend is paused or inactive. Audio callback will not be called until set_state has been called with true. -// Initial state is false (inactive). +/* True: Audio driver in frontend is active, and callback is + * expected to be called regularily. + * False: Audio driver in frontend is paused or inactive. + * Audio callback will not be called until set_state has been + * called with true. + * Initial state is false (inactive). + */ typedef void (*retro_audio_set_state_callback_t)(bool enabled); + struct retro_audio_callback { retro_audio_callback_t callback; retro_audio_set_state_callback_t set_state; }; -// Notifies a libretro core of time spent since last invocation of retro_run() in microseconds. -// It will be called right before retro_run() every frame. -// The frontend can tamper with timing to support cases like fast-forward, slow-motion and framestepping. -// In those scenarios the reference frame time value will be used. +/* Notifies a libretro core of time spent since last invocation + * of retro_run() in microseconds. + * + * It will be called right before retro_run() every frame. + * The frontend can tamper with timing to support cases like + * fast-forward, slow-motion and framestepping. + * + * In those scenarios the reference frame time value will be used. */ typedef int64_t retro_usec_t; typedef void (*retro_frame_time_callback_t)(retro_usec_t usec); struct retro_frame_time_callback { retro_frame_time_callback_t callback; - retro_usec_t reference; // Represents the time of one frame. It is computed as 1000000 / fps, but the implementation will resolve the rounding to ensure that framestepping, etc is exact. + /* Represents the time of one frame. It is computed as + * 1000000 / fps, but the implementation will resolve the + * rounding to ensure that framestepping, etc is exact. */ + retro_usec_t reference; }; -// Pass this to retro_video_refresh_t if rendering to hardware. -// Passing NULL to retro_video_refresh_t is still a frame dupe as normal. +/* Pass this to retro_video_refresh_t if rendering to hardware. + * Passing NULL to retro_video_refresh_t is still a frame dupe as normal. + * */ #define RETRO_HW_FRAME_BUFFER_VALID ((void*)-1) -// Invalidates the current HW context. -// Any GL state is lost, and must not be deinitialized explicitly. If explicit deinitialization is desired by the libretro core, -// it should implement context_destroy callback. -// If called, all GPU resources must be reinitialized. -// Usually called when frontend reinits video driver. -// Also called first time video driver is initialized, allowing libretro core to init resources. +/* Invalidates the current HW context. + * Any GL state is lost, and must not be deinitialized explicitly. + * If explicit deinitialization is desired by the libretro core, + * it should implement context_destroy callback. + * If called, all GPU resources must be reinitialized. + * Usually called when frontend reinits video driver. + * Also called first time video driver is initialized, + * allowing libretro core to initialize resources. + */ typedef void (*retro_hw_context_reset_t)(void); -// Gets current framebuffer which is to be rendered to. Could change every frame potentially. + +/* Gets current framebuffer which is to be rendered to. + * Could change every frame potentially. + */ typedef uintptr_t (*retro_hw_get_current_framebuffer_t)(void); -// Get a symbol from HW context. -typedef void (*retro_proc_address_t)(void); +/* Get a symbol from HW context. */ typedef retro_proc_address_t (*retro_hw_get_proc_address_t)(const char *sym); enum retro_hw_context_type { - RETRO_HW_CONTEXT_NONE = 0, - RETRO_HW_CONTEXT_OPENGL, // OpenGL 2.x. Latest version available before 3.x+. Driver can choose to use latest compatibility context. - RETRO_HW_CONTEXT_OPENGLES2, // GLES 2.0 - RETRO_HW_CONTEXT_OPENGL_CORE, // Modern desktop core GL context. Use major/minor fields to set GL version. - RETRO_HW_CONTEXT_OPENGLES3, // GLES 3.0 + RETRO_HW_CONTEXT_NONE = 0, + /* OpenGL 2.x. Driver can choose to use latest compatibility context. */ + RETRO_HW_CONTEXT_OPENGL = 1, + /* OpenGL ES 2.0. */ + RETRO_HW_CONTEXT_OPENGLES2 = 2, + /* Modern desktop core GL context. Use version_major/ + * version_minor fields to set GL version. */ + RETRO_HW_CONTEXT_OPENGL_CORE = 3, + /* OpenGL ES 3.0 */ + RETRO_HW_CONTEXT_OPENGLES3 = 4, + /* OpenGL ES 3.1+. Set version_major/version_minor. For GLES2 and GLES3, + * use the corresponding enums directly. */ + RETRO_HW_CONTEXT_OPENGLES_VERSION = 5, RETRO_HW_CONTEXT_DUMMY = INT_MAX }; struct retro_hw_render_callback { - enum retro_hw_context_type context_type; // Which API to use. Set by libretro core. - retro_hw_context_reset_t context_reset; // Called when a context has been created or when it has been reset. - retro_hw_get_current_framebuffer_t get_current_framebuffer; // Set by frontend. - retro_hw_get_proc_address_t get_proc_address; // Set by frontend. - bool depth; // Set if render buffers should have depth component attached. - bool stencil; // Set if stencil buffers should be attached. - // If depth and stencil are true, a packed 24/8 buffer will be added. Only attaching stencil is invalid and will be ignored. - bool bottom_left_origin; // Use conventional bottom-left origin convention. Is false, standard libretro top-left origin semantics are used. - unsigned version_major; // Major version number for core GL context. - unsigned version_minor; // Minor version number for core GL context. - - bool cache_context; // If this is true, the frontend will go very far to avoid resetting context in scenarios like toggling fullscreen, etc. - // The reset callback might still be called in extreme situations such as if the context is lost beyond recovery. - // For optimal stability, set this to false, and allow context to be reset at any time. - retro_hw_context_reset_t context_destroy; // A callback to be called before the context is destroyed. Resources can be deinitialized at this step. This can be set to NULL, in which resources will just be destroyed without any notification. - bool debug_context; // Creates a debug context. + /* Which API to use. Set by libretro core. */ + enum retro_hw_context_type context_type; + + /* Called when a context has been created or when it has been reset. + * An OpenGL context is only valid after context_reset() has been called. + * + * When context_reset is called, OpenGL resources in the libretro + * implementation are guaranteed to be invalid. + * + * It is possible that context_reset is called multiple times during an + * application lifecycle. + * If context_reset is called without any notification (context_destroy), + * the OpenGL context was lost and resources should just be recreated + * without any attempt to "free" old resources. + */ + retro_hw_context_reset_t context_reset; + + /* Set by frontend. */ + retro_hw_get_current_framebuffer_t get_current_framebuffer; + + /* Set by frontend. */ + retro_hw_get_proc_address_t get_proc_address; + + /* Set if render buffers should have depth component attached. */ + bool depth; + + /* Set if stencil buffers should be attached. */ + bool stencil; + + /* If depth and stencil are true, a packed 24/8 buffer will be added. + * Only attaching stencil is invalid and will be ignored. */ + + /* Use conventional bottom-left origin convention. If false, + * standard libretro top-left origin semantics are used. */ + bool bottom_left_origin; + + /* Major version number for core GL context or GLES 3.1+. */ + unsigned version_major; + + /* Minor version number for core GL context or GLES 3.1+. */ + unsigned version_minor; + + /* If this is true, the frontend will go very far to avoid + * resetting context in scenarios like toggling fullscreen, etc. + */ + bool cache_context; + + /* The reset callback might still be called in extreme situations + * such as if the context is lost beyond recovery. + * + * For optimal stability, set this to false, and allow context to be + * reset at any time. + */ + + /* A callback to be called before the context is destroyed in a + * controlled way by the frontend. */ + retro_hw_context_reset_t context_destroy; + + /* OpenGL resources can be deinitialized cleanly at this step. + * context_destroy can be set to NULL, in which resources will + * just be destroyed without any notification. + * + * Even when context_destroy is non-NULL, it is possible that + * context_reset is called without any destroy notification. + * This happens if context is lost by external factors (such as + * notified by GL_ARB_robustness). + * + * In this case, the context is assumed to be already dead, + * and the libretro implementation must not try to free any OpenGL + * resources in the subsequent context_reset. + */ + + /* Creates a debug context. */ + bool debug_context; }; -// Callback type passed in RETRO_ENVIRONMENT_SET_KEYBOARD_CALLBACK. Called by the frontend in response to keyboard events. -// down is set if the key is being pressed, or false if it is being released. -// keycode is the RETROK value of the char. -// character is the text character of the pressed key. (UTF-32). -// key_modifiers is a set of RETROKMOD values or'ed together. -// -// The pressed/keycode state can be indepedent of the character. -// It is also possible that multiple characters are generated from a single keypress. -// Keycode events should be treated separately from character events. -// However, when possible, the frontend should try to synchronize these. -// If only a character is posted, keycode should be RETROK_UNKNOWN. -// Similarily if only a keycode event is generated with no corresponding character, character should be 0. -typedef void (*retro_keyboard_event_t)(bool down, unsigned keycode, uint32_t character, uint16_t key_modifiers); +/* Callback type passed in RETRO_ENVIRONMENT_SET_KEYBOARD_CALLBACK. + * Called by the frontend in response to keyboard events. + * down is set if the key is being pressed, or false if it is being released. + * keycode is the RETROK value of the char. + * character is the text character of the pressed key. (UTF-32). + * key_modifiers is a set of RETROKMOD values or'ed together. + * + * The pressed/keycode state can be indepedent of the character. + * It is also possible that multiple characters are generated from a + * single keypress. + * Keycode events should be treated separately from character events. + * However, when possible, the frontend should try to synchronize these. + * If only a character is posted, keycode should be RETROK_UNKNOWN. + * + * Similarily if only a keycode event is generated with no corresponding + * character, character should be 0. + */ +typedef void (*retro_keyboard_event_t)(bool down, unsigned keycode, + uint32_t character, uint16_t key_modifiers); struct retro_keyboard_callback { retro_keyboard_event_t callback; }; -// Callbacks for RETRO_ENVIRONMENT_SET_DISK_CONTROL_INTERFACE. -// Should be set for implementations which can swap out multiple disk images in runtime. -// If the implementation can do this automatically, it should strive to do so. -// However, there are cases where the user must manually do so. -// -// Overview: To swap a disk image, eject the disk image with set_eject_state(true). -// Set the disk index with set_image_index(index). Insert the disk again with set_eject_state(false). +/* Callbacks for RETRO_ENVIRONMENT_SET_DISK_CONTROL_INTERFACE. + * Should be set for implementations which can swap out multiple disk + * images in runtime. + * + * If the implementation can do this automatically, it should strive to do so. + * However, there are cases where the user must manually do so. + * + * Overview: To swap a disk image, eject the disk image with + * set_eject_state(true). + * Set the disk index with set_image_index(index). Insert the disk again + * with set_eject_state(false). + */ -// If ejected is true, "ejects" the virtual disk tray. -// When ejected, the disk image index can be set. +/* If ejected is true, "ejects" the virtual disk tray. + * When ejected, the disk image index can be set. + */ typedef bool (*retro_set_eject_state_t)(bool ejected); -// Gets current eject state. The initial state is 'not ejected'. + +/* Gets current eject state. The initial state is 'not ejected'. */ typedef bool (*retro_get_eject_state_t)(void); -// Gets current disk index. First disk is index 0. -// If return value is >= get_num_images(), no disk is currently inserted. + +/* Gets current disk index. First disk is index 0. + * If return value is >= get_num_images(), no disk is currently inserted. + */ typedef unsigned (*retro_get_image_index_t)(void); -// Sets image index. Can only be called when disk is ejected. -// The implementation supports setting "no disk" by using an index >= get_num_images(). + +/* Sets image index. Can only be called when disk is ejected. + * The implementation supports setting "no disk" by using an + * index >= get_num_images(). + */ typedef bool (*retro_set_image_index_t)(unsigned index); -// Gets total number of images which are available to use. + +/* Gets total number of images which are available to use. */ typedef unsigned (*retro_get_num_images_t)(void); -// -// Replaces the disk image associated with index. -// Arguments to pass in info have same requirements as retro_load_game(). -// Virtual disk tray must be ejected when calling this. -// Replacing a disk image with info = NULL will remove the disk image from the internal list. -// As a result, calls to get_image_index() can change. -// -// E.g. replace_image_index(1, NULL), and previous get_image_index() returned 4 before. -// Index 1 will be removed, and the new index is 3. + struct retro_game_info; -typedef bool (*retro_replace_image_index_t)(unsigned index, const struct retro_game_info *info); -// Adds a new valid index (get_num_images()) to the internal disk list. -// This will increment subsequent return values from get_num_images() by 1. -// This image index cannot be used until a disk image has been set with replace_image_index. + +/* Replaces the disk image associated with index. + * Arguments to pass in info have same requirements as retro_load_game(). + * Virtual disk tray must be ejected when calling this. + * + * Replacing a disk image with info = NULL will remove the disk image + * from the internal list. + * As a result, calls to get_image_index() can change. + * + * E.g. replace_image_index(1, NULL), and previous get_image_index() + * returned 4 before. + * Index 1 will be removed, and the new index is 3. + */ +typedef bool (*retro_replace_image_index_t)(unsigned index, + const struct retro_game_info *info); + +/* Adds a new valid index (get_num_images()) to the internal disk list. + * This will increment subsequent return values from get_num_images() by 1. + * This image index cannot be used until a disk image has been set + * with replace_image_index. */ typedef bool (*retro_add_image_index_t)(void); struct retro_disk_control_callback @@ -907,81 +1643,105 @@ struct retro_disk_control_callback enum retro_pixel_format { - // 0RGB1555, native endian. 0 bit must be set to 0. - // This pixel format is default for compatibility concerns only. - // If a 15/16-bit pixel format is desired, consider using RGB565. + /* 0RGB1555, native endian. + * 0 bit must be set to 0. + * This pixel format is default for compatibility concerns only. + * If a 15/16-bit pixel format is desired, consider using RGB565. */ RETRO_PIXEL_FORMAT_0RGB1555 = 0, - // XRGB8888, native endian. X bits are ignored. + /* XRGB8888, native endian. + * X bits are ignored. */ RETRO_PIXEL_FORMAT_XRGB8888 = 1, - // RGB565, native endian. This pixel format is the recommended format to use if a 15/16-bit format is desired - // as it is the pixel format that is typically available on a wide range of low-power devices. - // It is also natively supported in APIs like OpenGL ES. + /* RGB565, native endian. + * This pixel format is the recommended format to use if a 15/16-bit + * format is desired as it is the pixel format that is typically + * available on a wide range of low-power devices. + * + * It is also natively supported in APIs like OpenGL ES. */ RETRO_PIXEL_FORMAT_RGB565 = 2, - // Ensure sizeof() == sizeof(int). + /* Ensure sizeof() == sizeof(int). */ RETRO_PIXEL_FORMAT_UNKNOWN = INT_MAX }; struct retro_message { - const char *msg; // Message to be displayed. - unsigned frames; // Duration in frames of message. + const char *msg; /* Message to be displayed. */ + unsigned frames; /* Duration in frames of message. */ }; -// Describes how the libretro implementation maps a libretro input bind -// to its internal input system through a human readable string. -// This string can be used to better let a user configure input. +/* Describes how the libretro implementation maps a libretro input bind + * to its internal input system through a human readable string. + * This string can be used to better let a user configure input. */ struct retro_input_descriptor { - // Associates given parameters with a description. + /* Associates given parameters with a description. */ unsigned port; unsigned device; unsigned index; unsigned id; - const char *description; // Human readable description for parameters. - // The pointer must remain valid until retro_unload_game() is called. + /* Human readable description for parameters. + * The pointer must remain valid until + * retro_unload_game() is called. */ + const char *description; }; struct retro_system_info { - // All pointers are owned by libretro implementation, and pointers must remain valid until retro_deinit() is called. - - const char *library_name; // Descriptive name of library. Should not contain any version numbers, etc. - const char *library_version; // Descriptive version of core. - - const char *valid_extensions; // A string listing probably rom extensions the core will be able to load, separated with pipe. - // I.e. "bin|rom|iso". - // Typically used for a GUI to filter out extensions. - - bool need_fullpath; // If true, retro_load_game() is guaranteed to provide a valid pathname in retro_game_info::path. - // ::data and ::size are both invalid. - // If false, ::data and ::size are guaranteed to be valid, but ::path might not be valid. - // This is typically set to true for libretro implementations that must load from file. - // Implementations should strive for setting this to false, as it allows the frontend to perform patching, etc. - - bool block_extract; // If true, the frontend is not allowed to extract any archives before loading the real ROM. - // Necessary for certain libretro implementations that load games from zipped archives. + /* All pointers are owned by libretro implementation, and pointers must + * remain valid until retro_deinit() is called. */ + + const char *library_name; /* Descriptive name of library. Should not + * contain any version numbers, etc. */ + const char *library_version; /* Descriptive version of core. */ + + const char *valid_extensions; /* A string listing probably content + * extensions the core will be able to + * load, separated with pipe. + * I.e. "bin|rom|iso". + * Typically used for a GUI to filter + * out extensions. */ + + /* If true, retro_load_game() is guaranteed to provide a valid pathname + * in retro_game_info::path. + * ::data and ::size are both invalid. + * + * If false, ::data and ::size are guaranteed to be valid, but ::path + * might not be valid. + * + * This is typically set to true for libretro implementations that must + * load from file. + * Implementations should strive for setting this to false, as it allows + * the frontend to perform patching, etc. */ + bool need_fullpath; + + /* If true, the frontend is not allowed to extract any archives before + * loading the real content. + * Necessary for certain libretro implementations that load games + * from zipped archives. */ + bool block_extract; }; struct retro_game_geometry { - unsigned base_width; // Nominal video width of game. - unsigned base_height; // Nominal video height of game. - unsigned max_width; // Maximum possible width of game. - unsigned max_height; // Maximum possible height of game. - - float aspect_ratio; // Nominal aspect ratio of game. If aspect_ratio is <= 0.0, - // an aspect ratio of base_width / base_height is assumed. - // A frontend could override this setting if desired. + unsigned base_width; /* Nominal video width of game. */ + unsigned base_height; /* Nominal video height of game. */ + unsigned max_width; /* Maximum possible width of game. */ + unsigned max_height; /* Maximum possible height of game. */ + + float aspect_ratio; /* Nominal aspect ratio of game. If + * aspect_ratio is <= 0.0, an aspect ratio + * of base_width / base_height is assumed. + * A frontend could override this setting, + * if desired. */ }; struct retro_system_timing { - double fps; // FPS of video content. - double sample_rate; // Sampling rate of audio. + double fps; /* FPS of video content. */ + double sample_rate; /* Sampling rate of audio. */ }; struct retro_system_av_info @@ -992,52 +1752,86 @@ struct retro_system_av_info struct retro_variable { - const char *key; // Variable to query in RETRO_ENVIRONMENT_GET_VARIABLE. - // If NULL, obtains the complete environment string if more complex parsing is necessary. - // The environment string is formatted as key-value pairs delimited by semicolons as so: - // "key1=value1;key2=value2;..." - const char *value; // Value to be obtained. If key does not exist, it is set to NULL. + /* Variable to query in RETRO_ENVIRONMENT_GET_VARIABLE. + * If NULL, obtains the complete environment string if more + * complex parsing is necessary. + * The environment string is formatted as key-value pairs + * delimited by semicolons as so: + * "key1=value1;key2=value2;..." + */ + const char *key; + + /* Value to be obtained. If key does not exist, it is set to NULL. */ + const char *value; }; struct retro_game_info { - const char *path; // Path to game, UTF-8 encoded. Usually used as a reference. - // May be NULL if rom was loaded from stdin or similar. - // retro_system_info::need_fullpath guaranteed that this path is valid. - const void *data; // Memory buffer of loaded game. Will be NULL if need_fullpath was set. - size_t size; // Size of memory buffer. - const char *meta; // String of implementation specific meta-data. + const char *path; /* Path to game, UTF-8 encoded. + * Usually used as a reference. + * May be NULL if rom was loaded from stdin + * or similar. + * retro_system_info::need_fullpath guaranteed + * that this path is valid. */ + const void *data; /* Memory buffer of loaded game. Will be NULL + * if need_fullpath was set. */ + size_t size; /* Size of memory buffer. */ + const char *meta; /* String of implementation specific meta-data. */ }; -// Callbacks -// -// Environment callback. Gives implementations a way of performing uncommon tasks. Extensible. +/* Callbacks */ + +/* Environment callback. Gives implementations a way of performing + * uncommon tasks. Extensible. */ typedef bool (*retro_environment_t)(unsigned cmd, void *data); -// Render a frame. Pixel format is 15-bit 0RGB1555 native endian unless changed (see RETRO_ENVIRONMENT_SET_PIXEL_FORMAT). -// Width and height specify dimensions of buffer. -// Pitch specifices length in bytes between two lines in buffer. -// For performance reasons, it is highly recommended to have a frame that is packed in memory, i.e. pitch == width * byte_per_pixel. -// Certain graphic APIs, such as OpenGL ES, do not like textures that are not packed in memory. -typedef void (*retro_video_refresh_t)(const void *data, unsigned width, unsigned height, size_t pitch); +/* Render a frame. Pixel format is 15-bit 0RGB1555 native endian + * unless changed (see RETRO_ENVIRONMENT_SET_PIXEL_FORMAT). + * + * Width and height specify dimensions of buffer. + * Pitch specifices length in bytes between two lines in buffer. + * + * For performance reasons, it is highly recommended to have a frame + * that is packed in memory, i.e. pitch == width * byte_per_pixel. + * Certain graphic APIs, such as OpenGL ES, do not like textures + * that are not packed in memory. + */ +typedef void (*retro_video_refresh_t)(const void *data, unsigned width, + unsigned height, size_t pitch); -// Renders a single audio frame. Should only be used if implementation generates a single sample at a time. -// Format is signed 16-bit native endian. +/* Renders a single audio frame. Should only be used if implementation + * generates a single sample at a time. + * Format is signed 16-bit native endian. + */ typedef void (*retro_audio_sample_t)(int16_t left, int16_t right); -// Renders multiple audio frames in one go. One frame is defined as a sample of left and right channels, interleaved. -// I.e. int16_t buf[4] = { l, r, l, r }; would be 2 frames. -// Only one of the audio callbacks must ever be used. -typedef size_t (*retro_audio_sample_batch_t)(const int16_t *data, size_t frames); -// Polls input. +/* Renders multiple audio frames in one go. + * + * One frame is defined as a sample of left and right channels, interleaved. + * I.e. int16_t buf[4] = { l, r, l, r }; would be 2 frames. + * Only one of the audio callbacks must ever be used. + */ +typedef size_t (*retro_audio_sample_batch_t)(const int16_t *data, + size_t frames); + +/* Polls input. */ typedef void (*retro_input_poll_t)(void); -// Queries for input for player 'port'. device will be masked with RETRO_DEVICE_MASK. -// Specialization of devices such as RETRO_DEVICE_JOYPAD_MULTITAP that have been set with retro_set_controller_port_device() -// will still use the higher level RETRO_DEVICE_JOYPAD to request input. -typedef int16_t (*retro_input_state_t)(unsigned port, unsigned device, unsigned index, unsigned id); -// Sets callbacks. retro_set_environment() is guaranteed to be called before retro_init(). -// The rest of the set_* functions are guaranteed to have been called before the first call to retro_run() is made. +/* Queries for input for player 'port'. device will be masked with + * RETRO_DEVICE_MASK. + * + * Specialization of devices such as RETRO_DEVICE_JOYPAD_MULTITAP that + * have been set with retro_set_controller_port_device() + * will still use the higher level RETRO_DEVICE_JOYPAD to request input. + */ +typedef int16_t (*retro_input_state_t)(unsigned port, unsigned device, + unsigned index, unsigned id); + +/* Sets callbacks. retro_set_environment() is guaranteed to be called + * before retro_init(). + * + * The rest of the set_* functions are guaranteed to have been called + * before the first call to retro_run() is made. */ void retro_set_environment(retro_environment_t); void retro_set_video_refresh(retro_video_refresh_t); void retro_set_audio_sample(retro_audio_sample_t); @@ -1045,65 +1839,83 @@ void retro_set_audio_sample_batch(retro_audio_sample_batch_t); void retro_set_input_poll(retro_input_poll_t); void retro_set_input_state(retro_input_state_t); -// Library global initialization/deinitialization. +/* Library global initialization/deinitialization. */ void retro_init(void); void retro_deinit(void); -// Must return RETRO_API_VERSION. Used to validate ABI compatibility when the API is revised. +/* Must return RETRO_API_VERSION. Used to validate ABI compatibility + * when the API is revised. */ unsigned retro_api_version(void); -// Gets statically known system info. Pointers provided in *info must be statically allocated. -// Can be called at any time, even before retro_init(). +/* Gets statically known system info. Pointers provided in *info + * must be statically allocated. + * Can be called at any time, even before retro_init(). */ void retro_get_system_info(struct retro_system_info *info); -// Gets information about system audio/video timings and geometry. -// Can be called only after retro_load_game() has successfully completed. -// NOTE: The implementation of this function might not initialize every variable if needed. -// E.g. geom.aspect_ratio might not be initialized if core doesn't desire a particular aspect ratio. +/* Gets information about system audio/video timings and geometry. + * Can be called only after retro_load_game() has successfully completed. + * NOTE: The implementation of this function might not initialize every + * variable if needed. + * E.g. geom.aspect_ratio might not be initialized if core doesn't + * desire a particular aspect ratio. */ void retro_get_system_av_info(struct retro_system_av_info *info); -// Sets device to be used for player 'port'. +/* Sets device to be used for player 'port'. + * By default, RETRO_DEVICE_JOYPAD is assumed to be plugged into all + * available ports. + * Setting a particular device type is not a guarantee that libretro cores + * will only poll input based on that particular device type. It is only a + * hint to the libretro core when a core cannot automatically detect the + * appropriate input device type on its own. It is also relevant when a + * core can change its behavior depending on device type. */ void retro_set_controller_port_device(unsigned port, unsigned device); -// Resets the current game. +/* Resets the current game. */ void retro_reset(void); -// Runs the game for one video frame. -// During retro_run(), input_poll callback must be called at least once. -// -// If a frame is not rendered for reasons where a game "dropped" a frame, -// this still counts as a frame, and retro_run() should explicitly dupe a frame if GET_CAN_DUPE returns true. -// In this case, the video callback can take a NULL argument for data. +/* Runs the game for one video frame. + * During retro_run(), input_poll callback must be called at least once. + * + * If a frame is not rendered for reasons where a game "dropped" a frame, + * this still counts as a frame, and retro_run() should explicitly dupe + * a frame if GET_CAN_DUPE returns true. + * In this case, the video callback can take a NULL argument for data. + */ void retro_run(void); -// Returns the amount of data the implementation requires to serialize internal state (save states). -// Beetween calls to retro_load_game() and retro_unload_game(), the returned size is never allowed to be larger than a previous returned value, to -// ensure that the frontend can allocate a save state buffer once. +/* Returns the amount of data the implementation requires to serialize + * internal state (save states). + * Between calls to retro_load_game() and retro_unload_game(), the + * returned size is never allowed to be larger than a previous returned + * value, to ensure that the frontend can allocate a save state buffer once. + */ size_t retro_serialize_size(void); -// Serializes internal state. If failed, or size is lower than retro_serialize_size(), it should return false, true otherwise. +/* Serializes internal state. If failed, or size is lower than + * retro_serialize_size(), it should return false, true otherwise. */ bool retro_serialize(void *data, size_t size); bool retro_unserialize(const void *data, size_t size); void retro_cheat_reset(void); void retro_cheat_set(unsigned index, bool enabled, const char *code); -// Loads a game. +/* Loads a game. */ bool retro_load_game(const struct retro_game_info *game); -// Loads a "special" kind of game. Should not be used except in extreme cases. +/* Loads a "special" kind of game. Should not be used, + * except in extreme cases. */ bool retro_load_game_special( unsigned game_type, const struct retro_game_info *info, size_t num_info ); -// Unloads a currently loaded game. +/* Unloads a currently loaded game. */ void retro_unload_game(void); -// Gets region of game. +/* Gets region of game. */ unsigned retro_get_region(void); -// Gets region of memory. +/* Gets region of memory. */ void *retro_get_memory_data(unsigned id); size_t retro_get_memory_size(unsigned id); -- cgit v1.2.3 From de2a99184b5e478a39a2cb82872d8d5c4af0f3f6 Mon Sep 17 00:00:00 2001 From: twinaphex Date: Thu, 23 Oct 2014 09:36:14 +0200 Subject: Update Makefile --- Makefile.libretro | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/Makefile.libretro b/Makefile.libretro index 7c16422..b92cea4 100644 --- a/Makefile.libretro +++ b/Makefile.libretro @@ -33,8 +33,9 @@ else ifeq ($(platform), osx) SHARED := -dynamiclib BUILTIN_GPU = neon CFLAGS += -DNEON_PC -OSXVER = `sw_vers -productVersion | cut -c 4` -ifneq ($(OSXVER),9) + OSXVER = `sw_vers -productVersion | cut -d. -f 2` + OSX_LT_MAVERICKS = `(( $(OSXVER) <= 9)) && echo "YES"` +ifeq ($(OSX_LT_MAVERICKS),"YES") fpic += -mmacosx-version-min=10.5 endif else ifeq ($(platform), ios) @@ -43,6 +44,10 @@ ARCH := arm fpic := -fPIC SHARED := -dynamiclib +ifeq ($(IOSSDK),) + IOSSDK := $(shell xcrun -sdk iphoneos -show-sdk-path) +endif + CC = clang -arch armv7 -isysroot $(IOSSDK) CXX = clang++ -arch armv7 -isysroot $(IOSSDK) CC_AS = perl ./tools/gas-preprocessor.pl $(CC) @@ -52,8 +57,9 @@ ARCH := arm BUILTIN_GPU = neon USE_DYNAREC = 1 CFLAGS += -DIOS -OSXVER = `sw_vers -productVersion | cut -c 4` -ifneq ($(OSXVER),9) + OSXVER = `sw_vers -productVersion | cut -d. -f 2` + OSX_LT_MAVERICKS = `(( $(OSXVER) <= 9)) && echo "YES"` +ifeq ($(OSX_LT_MAVERICKS),"YES") CC += -miphoneos-version-min=5.0 CXX += -miphoneos-version-min=5.0 CC_AS += -miphoneos-version-min=5.0 -- cgit v1.2.3 From 8d24cb85c2a67040aff70716f317fd6d37777dd5 Mon Sep 17 00:00:00 2001 From: ksv1986 Date: Sat, 29 Nov 2014 17:15:37 +0300 Subject: libretro: Add rumble support --- frontend/libretro.c | 35 ++++++++++++++++++-------- include/psemu_plugin_defs.h | 6 ++++- plugins/dfinput/externals.h | 2 +- plugins/dfinput/pad.c | 60 ++++++++++++++++++++++++++++----------------- 4 files changed, 69 insertions(+), 34 deletions(-) diff --git a/frontend/libretro.c b/frontend/libretro.c index e5496cb..3b8975f 100644 --- a/frontend/libretro.c +++ b/frontend/libretro.c @@ -32,6 +32,7 @@ static retro_input_poll_t input_poll_cb; static retro_input_state_t input_state_cb; static retro_environment_t environ_cb; static retro_audio_sample_batch_t audio_batch_cb; +static struct retro_rumble_interface rumble; static void *vout_buf; static int vout_width, vout_height; @@ -51,7 +52,7 @@ extern char McdDisable[2]; int in_type1, in_type2; int in_a1[2] = { 127, 127 }, in_a2[2] = { 127, 127 }; int in_keystate; -int in_enable_vibration; +int in_enable_vibration = 1; /* PSX max resolution is 640x512, but with enhancement it's 1024x512 */ #define VOUT_MAX_WIDTH 1024 @@ -196,8 +197,10 @@ void pl_timing_prepare(int is_pal) is_pal_mode = is_pal; } -void plat_trigger_vibrate(int is_strong) +void plat_trigger_vibrate(int pad, uint32_t low, uint32_t high) { + rumble.set_rumble_state(pad, RETRO_RUMBLE_STRONG, high << 8); + rumble.set_rumble_state(pad, RETRO_RUMBLE_WEAK, low ? 0xffff : 0x0); } void pl_update_gun(int *xn, int *yn, int *xres, int *yres, int *in) @@ -241,11 +244,12 @@ void out_register_libretro(struct out_driver *drv) void retro_set_environment(retro_environment_t cb) { static const struct retro_variable vars[] = { - { "frameskip", "Frameskip; 0|1|2|3" }, - { "region", "Region; Auto|NTSC|PAL" }, - { "pad1type", "Pad 1 Type; standard|analog" }, + { "pcsx_rearmed_frameskip", "Frameskip; 0|1|2|3" }, + { "pcsx_rearmed_region", "Region; Auto|NTSC|PAL" }, + { "pcsx_rearmed_pad1type", "Pad 1 Type; standard|analog" }, + { "pcsx_rearmed_pad2type", "Pad 2 Type; standard|analog" }, #ifndef DRC_DISABLE - { "rearmed_drc", "Dynamic recompiler; enabled|disabled" }, + { "pcsx_rearmed_drc", "Dynamic recompiler; enabled|disabled" }, #endif #if defined(__ARM_NEON__) || defined(NEON_PC) { "neon_interlace_enable", "Enable interlacing mode(s); disabled|enabled" }, @@ -773,13 +777,13 @@ static void update_variables(bool in_flight) struct retro_variable var; var.value = NULL; - var.key = "frameskip"; + var.key = "pcsx_rearmed_frameskip"; if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) || var.value) pl_rearmed_cbs.frameskip = atoi(var.value); var.value = NULL; - var.key = "region"; + var.key = "pcsx_rearmed_region"; if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) || var.value) { @@ -793,7 +797,7 @@ static void update_variables(bool in_flight) } var.value = NULL; - var.key = "pad1type"; + var.key = "pcsx_rearmed_pad1type"; if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) || var.value) { @@ -802,6 +806,16 @@ static void update_variables(bool in_flight) in_type1 = PSE_PAD_TYPE_ANALOGPAD; } + var.value = NULL; + var.key = "pcsx_rearmed_pad2type"; + + if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) || var.value) + { + in_type2 = PSE_PAD_TYPE_STANDARD; + if (strcmp(var.value, "analog") == 0) + in_type2 = PSE_PAD_TYPE_ANALOGPAD; + } + #if defined(__ARM_NEON__) || defined(NEON_PC) var.value = "NULL"; var.key = "neon_interlace_enable"; @@ -850,7 +864,7 @@ static void update_variables(bool in_flight) #ifndef DRC_DISABLE var.value = NULL; - var.key = "rearmed_drc"; + var.key = "pcsx_rearmed_drc"; if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) || var.value) { @@ -1034,6 +1048,7 @@ void retro_init(void) environ_cb(RETRO_ENVIRONMENT_GET_CAN_DUPE, &vout_can_dupe); environ_cb(RETRO_ENVIRONMENT_SET_DISK_CONTROL_INTERFACE, &disk_control); + environ_cb(RETRO_ENVIRONMENT_GET_RUMBLE_INTERFACE, &rumble); /* Set how much slower PSX CPU runs * 100 (so that 200 is 2 times) * we have to do this because cache misses and some IO penalties diff --git a/include/psemu_plugin_defs.h b/include/psemu_plugin_defs.h index 3926ccd..0805f4a 100644 --- a/include/psemu_plugin_defs.h +++ b/include/psemu_plugin_defs.h @@ -205,7 +205,11 @@ typedef struct // values are in range -128 - 127 unsigned char moveX, moveY; - unsigned char reserved[91]; + uint8_t Vib[2]; + + volatile uint8_t VibF[2]; + + unsigned char reserved[87]; } PadDataS; diff --git a/plugins/dfinput/externals.h b/plugins/dfinput/externals.h index 5419977..042d9dc 100644 --- a/plugins/dfinput/externals.h +++ b/plugins/dfinput/externals.h @@ -11,4 +11,4 @@ extern void pl_update_gun(int *xn, int *yn, int *xres, int *yres, int *in); /* vibration trigger to frontend */ extern int in_enable_vibration; -extern void plat_trigger_vibrate(int is_strong); +extern void plat_trigger_vibrate(int pad, uint32_t low, uint32_t high); diff --git a/plugins/dfinput/pad.c b/plugins/dfinput/pad.c index 53a254a..348bb8f 100644 --- a/plugins/dfinput/pad.c +++ b/plugins/dfinput/pad.c @@ -203,22 +203,41 @@ static void do_cmd2(unsigned char value) break; } break; - - case CMD_READ_DATA_AND_VIBRATE: - if (value == 1 && CurPad == 0 && in_enable_vibration) - plat_trigger_vibrate(0); - break; } } static void do_cmd3(unsigned char value) { - if (in_enable_vibration && CurCmd == CMD_READ_DATA_AND_VIBRATE && CurPad == 0) { - if (value >= 0xf0) - plat_trigger_vibrate(1); - else if (value > 0x40) - plat_trigger_vibrate(0); - } + int i; + switch (CurCmd) { + case CMD_READ_DATA_AND_VIBRATE: + if (!in_enable_vibration) + break; + if (padstate[CurPad].pad.controllerType != PSE_PAD_TYPE_ANALOGPAD) + break; + + for (i = 0; i < 2; i++) { + if (padstate[CurPad].pad.Vib[i] == CurByte) + padstate[CurPad].pad.VibF[i] = value; + } + + plat_trigger_vibrate(CurPad, + padstate[CurPad].pad.VibF[0], + padstate[CurPad].pad.VibF[1]); + break; + case CMD_VIBRATION_TOGGLE: + for (i = 0; i < 2; i++) { + if (padstate[CurPad].pad.Vib[i] == CurByte) + buf[CurByte] = 0; + } + if (value < 2) { + padstate[CurPad].pad.Vib[value] = CurByte; + if((padstate[CurPad].PadID & 0x0f) < (CurByte - 1) / 2) { + padstate[CurPad].PadID = (padstate[CurPad].PadID & 0xf0) + (CurByte - 1) / 2; + } + } + break; + } } #if 0 @@ -233,9 +252,7 @@ unsigned char PADpoll(unsigned char value) { #endif unsigned char PADpoll_pad(unsigned char value) { - - switch (CurByte) { - case 0: + if (CurByte == 0) { CurCmd = value; CurByte++; @@ -244,16 +261,15 @@ unsigned char PADpoll_pad(unsigned char value) { CurCmd = CMD_READ_DATA_AND_VIBRATE; return do_cmd(); - case 2: + } + + if (CurByte >= CmdLen) + return 0xff; // verified + + if (CurByte == 2) do_cmd2(value); - break; - case 3: - do_cmd3(value); - break; - } - if (CurByte >= CmdLen) - return 0xff; // verified + do_cmd3(value); return buf[CurByte++]; } -- cgit v1.2.3 From 8ddd009b7531148f4c2a24e0e327a541a24eb213 Mon Sep 17 00:00:00 2001 From: twinaphex Date: Thu, 4 Dec 2014 14:03:55 +0100 Subject: 1) Build fix 2) Implement input descriptors --- frontend/libretro.c | 142 ++++++++++++++++++++++++++++++++++++++++++++ include/psemu_plugin_defs.h | 2 + 2 files changed, 144 insertions(+) diff --git a/frontend/libretro.c b/frontend/libretro.c index 3b8975f..bce2da7 100644 --- a/frontend/libretro.c +++ b/frontend/libretro.c @@ -634,6 +634,148 @@ bool retro_load_game(const struct retro_game_info *info) size_t i; bool is_m3u = (strcasestr(info->path, ".m3u") != NULL); + struct retro_input_descriptor desc[] = { + { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_LEFT, "D-Pad Left" }, + { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_UP, "D-Pad Up" }, + { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_DOWN, "D-Pad Down" }, + { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_RIGHT, "D-Pad Right" }, + { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_B, "Cross" }, + { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_A, "Circle" }, + { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_X, "Triangle" }, + { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_Y, "Square" }, + { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_L, "L1" }, + { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_L2, "L2" }, + { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_L3, "L3" }, + { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_R, "R1" }, + { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_R2, "R2" }, + { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_R3, "R3" }, + { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_SELECT, "Select" }, + { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_START, "Start" }, + + { 1, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_LEFT, "D-Pad Left" }, + { 1, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_UP, "D-Pad Up" }, + { 1, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_DOWN, "D-Pad Down" }, + { 1, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_RIGHT, "D-Pad Right" }, + { 1, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_B, "Cross" }, + { 1, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_A, "Circle" }, + { 1, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_X, "Triangle" }, + { 1, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_Y, "Square" }, + { 1, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_L, "L1" }, + { 1, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_L2, "L2" }, + { 1, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_L3, "L3" }, + { 1, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_R, "R1" }, + { 1, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_R2, "R2" }, + { 1, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_R3, "R3" }, + { 1, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_SELECT, "Select" }, + { 1, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_START, "Start" }, + + { 2, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_LEFT, "D-Pad Left" }, + { 2, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_UP, "D-Pad Up" }, + { 2, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_DOWN, "D-Pad Down" }, + { 2, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_RIGHT, "D-Pad Right" }, + { 2, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_B, "Cross" }, + { 2, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_A, "Circle" }, + { 2, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_X, "Triangle" }, + { 2, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_Y, "Square" }, + { 2, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_L, "L1" }, + { 2, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_L2, "L2" }, + { 2, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_L3, "L3" }, + { 2, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_R, "R1" }, + { 2, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_R2, "R2" }, + { 2, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_R3, "R3" }, + { 2, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_SELECT, "Select" }, + { 2, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_START, "Start" }, + + { 3, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_LEFT, "D-Pad Left" }, + { 3, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_UP, "D-Pad Up" }, + { 3, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_DOWN, "D-Pad Down" }, + { 3, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_RIGHT, "D-Pad Right" }, + { 3, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_B, "Cross" }, + { 3, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_A, "Circle" }, + { 3, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_X, "Triangle" }, + { 3, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_Y, "Square" }, + { 3, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_L, "L1" }, + { 3, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_L2, "L2" }, + { 3, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_L3, "L3" }, + { 3, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_R, "R1" }, + { 3, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_R2, "R2" }, + { 3, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_R3, "R3" }, + { 3, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_SELECT, "Select" }, + { 3, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_START, "Start" }, + + { 4, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_LEFT, "D-Pad Left" }, + { 4, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_UP, "D-Pad Up" }, + { 4, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_DOWN, "D-Pad Down" }, + { 4, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_RIGHT, "D-Pad Right" }, + { 4, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_B, "Cross" }, + { 4, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_A, "Circle" }, + { 4, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_X, "Triangle" }, + { 4, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_Y, "Square" }, + { 4, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_L, "L1" }, + { 4, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_L2, "L2" }, + { 4, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_L3, "L3" }, + { 4, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_R, "R1" }, + { 4, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_R2, "R2" }, + { 4, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_R3, "R3" }, + { 4, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_SELECT, "Select" }, + { 4, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_START, "Start" }, + + { 5, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_LEFT, "D-Pad Left" }, + { 5, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_UP, "D-Pad Up" }, + { 5, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_DOWN, "D-Pad Down" }, + { 5, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_RIGHT, "D-Pad Right" }, + { 5, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_B, "Cross" }, + { 5, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_A, "Circle" }, + { 5, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_X, "Triangle" }, + { 5, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_Y, "Square" }, + { 5, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_L, "L1" }, + { 5, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_L2, "L2" }, + { 5, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_L3, "L3" }, + { 5, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_R, "R1" }, + { 5, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_R2, "R2" }, + { 5, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_R3, "R3" }, + { 5, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_SELECT, "Select" }, + { 5, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_START, "Start" }, + + { 6, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_LEFT, "D-Pad Left" }, + { 6, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_UP, "D-Pad Up" }, + { 6, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_DOWN, "D-Pad Down" }, + { 6, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_RIGHT, "D-Pad Right" }, + { 6, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_B, "Cross" }, + { 6, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_A, "Circle" }, + { 6, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_X, "Triangle" }, + { 6, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_Y, "Square" }, + { 6, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_L, "L1" }, + { 6, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_L2, "L2" }, + { 6, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_L3, "L3" }, + { 6, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_R, "R1" }, + { 6, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_R2, "R2" }, + { 6, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_R3, "R3" }, + { 6, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_SELECT, "Select" }, + { 6, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_START, "Start" }, + + { 7, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_LEFT, "D-Pad Left" }, + { 7, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_UP, "D-Pad Up" }, + { 7, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_DOWN, "D-Pad Down" }, + { 7, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_RIGHT, "D-Pad Right" }, + { 7, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_B, "Cross" }, + { 7, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_A, "Circle" }, + { 7, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_X, "Triangle" }, + { 7, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_Y, "Square" }, + { 7, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_L, "L1" }, + { 7, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_L2, "L2" }, + { 7, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_L3, "L3" }, + { 7, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_R, "R1" }, + { 7, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_R2, "R2" }, + { 7, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_R3, "R3" }, + { 7, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_SELECT, "Select" }, + { 7, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_START, "Start" }, + + { 0 }, + }; + + environ_cb(RETRO_ENVIRONMENT_SET_INPUT_DESCRIPTORS, desc); + #ifdef FRONTEND_SUPPORTS_RGB565 enum retro_pixel_format fmt = RETRO_PIXEL_FORMAT_RGB565; if (environ_cb(RETRO_ENVIRONMENT_SET_PIXEL_FORMAT, &fmt)) { diff --git a/include/psemu_plugin_defs.h b/include/psemu_plugin_defs.h index 0805f4a..b40c77c 100644 --- a/include/psemu_plugin_defs.h +++ b/include/psemu_plugin_defs.h @@ -5,6 +5,8 @@ extern "C" { #endif +#include + // header version #define _PPDK_HEADER_VERSION 3 -- cgit v1.2.3 From 84f18c09cddd97d888992578150a3f4c5e6830da Mon Sep 17 00:00:00 2001 From: twinaphex Date: Thu, 4 Dec 2014 14:55:42 +0100 Subject: Update input descriptors --- frontend/libretro.c | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/frontend/libretro.c b/frontend/libretro.c index bce2da7..ca9769e 100644 --- a/frontend/libretro.c +++ b/frontend/libretro.c @@ -651,6 +651,11 @@ bool retro_load_game(const struct retro_game_info *info) { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_R3, "R3" }, { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_SELECT, "Select" }, { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_START, "Start" }, + { 0, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_LEFT, RETRO_DEVICE_ID_ANALOG_X, "Left Analog X" }, + { 0, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_LEFT, RETRO_DEVICE_ID_ANALOG_Y, "Left Analog Y" }, + { 0, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_RIGHT, RETRO_DEVICE_ID_ANALOG_X, "Right Analog X" }, + { 0, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_RIGHT, RETRO_DEVICE_ID_ANALOG_Y, "Right Analog Y" }, + { 1, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_LEFT, "D-Pad Left" }, { 1, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_UP, "D-Pad Up" }, @@ -668,6 +673,10 @@ bool retro_load_game(const struct retro_game_info *info) { 1, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_R3, "R3" }, { 1, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_SELECT, "Select" }, { 1, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_START, "Start" }, + { 1, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_LEFT, RETRO_DEVICE_ID_ANALOG_X, "Left Analog X" }, + { 1, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_LEFT, RETRO_DEVICE_ID_ANALOG_Y, "Left Analog Y" }, + { 1, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_RIGHT, RETRO_DEVICE_ID_ANALOG_X, "Right Analog X" }, + { 1, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_RIGHT, RETRO_DEVICE_ID_ANALOG_Y, "Right Analog Y" }, { 2, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_LEFT, "D-Pad Left" }, { 2, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_UP, "D-Pad Up" }, @@ -685,6 +694,10 @@ bool retro_load_game(const struct retro_game_info *info) { 2, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_R3, "R3" }, { 2, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_SELECT, "Select" }, { 2, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_START, "Start" }, + { 2, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_LEFT, RETRO_DEVICE_ID_ANALOG_X, "Left Analog X" }, + { 2, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_LEFT, RETRO_DEVICE_ID_ANALOG_Y, "Left Analog Y" }, + { 2, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_RIGHT, RETRO_DEVICE_ID_ANALOG_X, "Right Analog X" }, + { 2, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_RIGHT, RETRO_DEVICE_ID_ANALOG_Y, "Right Analog Y" }, { 3, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_LEFT, "D-Pad Left" }, { 3, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_UP, "D-Pad Up" }, @@ -702,6 +715,10 @@ bool retro_load_game(const struct retro_game_info *info) { 3, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_R3, "R3" }, { 3, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_SELECT, "Select" }, { 3, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_START, "Start" }, + { 3, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_LEFT, RETRO_DEVICE_ID_ANALOG_X, "Left Analog X" }, + { 3, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_LEFT, RETRO_DEVICE_ID_ANALOG_Y, "Left Analog Y" }, + { 3, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_RIGHT, RETRO_DEVICE_ID_ANALOG_X, "Right Analog X" }, + { 3, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_RIGHT, RETRO_DEVICE_ID_ANALOG_Y, "Right Analog Y" }, { 4, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_LEFT, "D-Pad Left" }, { 4, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_UP, "D-Pad Up" }, @@ -719,6 +736,10 @@ bool retro_load_game(const struct retro_game_info *info) { 4, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_R3, "R3" }, { 4, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_SELECT, "Select" }, { 4, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_START, "Start" }, + { 4, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_LEFT, RETRO_DEVICE_ID_ANALOG_X, "Left Analog X" }, + { 4, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_LEFT, RETRO_DEVICE_ID_ANALOG_Y, "Left Analog Y" }, + { 4, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_RIGHT, RETRO_DEVICE_ID_ANALOG_X, "Right Analog X" }, + { 4, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_RIGHT, RETRO_DEVICE_ID_ANALOG_Y, "Right Analog Y" }, { 5, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_LEFT, "D-Pad Left" }, { 5, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_UP, "D-Pad Up" }, @@ -736,6 +757,10 @@ bool retro_load_game(const struct retro_game_info *info) { 5, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_R3, "R3" }, { 5, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_SELECT, "Select" }, { 5, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_START, "Start" }, + { 5, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_LEFT, RETRO_DEVICE_ID_ANALOG_X, "Left Analog X" }, + { 5, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_LEFT, RETRO_DEVICE_ID_ANALOG_Y, "Left Analog Y" }, + { 5, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_RIGHT, RETRO_DEVICE_ID_ANALOG_X, "Right Analog X" }, + { 5, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_RIGHT, RETRO_DEVICE_ID_ANALOG_Y, "Right Analog Y" }, { 6, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_LEFT, "D-Pad Left" }, { 6, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_UP, "D-Pad Up" }, @@ -753,6 +778,10 @@ bool retro_load_game(const struct retro_game_info *info) { 6, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_R3, "R3" }, { 6, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_SELECT, "Select" }, { 6, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_START, "Start" }, + { 6, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_LEFT, RETRO_DEVICE_ID_ANALOG_X, "Left Analog X" }, + { 6, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_LEFT, RETRO_DEVICE_ID_ANALOG_Y, "Left Analog Y" }, + { 6, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_RIGHT, RETRO_DEVICE_ID_ANALOG_X, "Right Analog X" }, + { 6, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_RIGHT, RETRO_DEVICE_ID_ANALOG_Y, "Right Analog Y" }, { 7, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_LEFT, "D-Pad Left" }, { 7, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_UP, "D-Pad Up" }, @@ -770,6 +799,10 @@ bool retro_load_game(const struct retro_game_info *info) { 7, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_R3, "R3" }, { 7, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_SELECT, "Select" }, { 7, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_START, "Start" }, + { 7, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_LEFT, RETRO_DEVICE_ID_ANALOG_X, "Left Analog X" }, + { 7, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_LEFT, RETRO_DEVICE_ID_ANALOG_Y, "Left Analog Y" }, + { 7, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_RIGHT, RETRO_DEVICE_ID_ANALOG_X, "Right Analog X" }, + { 7, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_RIGHT, RETRO_DEVICE_ID_ANALOG_Y, "Right Analog Y" }, { 0 }, }; -- cgit v1.2.3 From 89329f140b3a7982dd3529ab374195b0e0b23dc8 Mon Sep 17 00:00:00 2001 From: twinaphex Date: Fri, 5 Dec 2014 22:08:02 +0100 Subject: Add core options to namespace --- frontend/libretro.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/frontend/libretro.c b/frontend/libretro.c index ca9769e..cd889c2 100644 --- a/frontend/libretro.c +++ b/frontend/libretro.c @@ -252,9 +252,9 @@ void retro_set_environment(retro_environment_t cb) { "pcsx_rearmed_drc", "Dynamic recompiler; enabled|disabled" }, #endif #if defined(__ARM_NEON__) || defined(NEON_PC) - { "neon_interlace_enable", "Enable interlacing mode(s); disabled|enabled" }, - { "neon_enhancement_enable", "Enhanced resolution (slow); disabled|enabled" }, - { "neon_enhancement_no_main", "Enhanced resolution speed hack; disabled|enabled" }, + { "pcsx_rearmed_neon_interlace_enable", "Enable interlacing mode(s); disabled|enabled" }, + { "pcsx_rearmed_neon_enhancement_enable", "Enhanced resolution (slow); disabled|enabled" }, + { "pcsx_rearmed_neon_enhancement_no_main", "Enhanced resolution speed hack; disabled|enabled" }, #endif { "pcsx_rearmed_duping_enable", "Frame duping; on|off" }, { NULL, NULL }, @@ -993,7 +993,7 @@ static void update_variables(bool in_flight) #if defined(__ARM_NEON__) || defined(NEON_PC) var.value = "NULL"; - var.key = "neon_interlace_enable"; + var.key = "pcsx_rearmed_neon_interlace_enable"; if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) || var.value) { @@ -1004,7 +1004,7 @@ static void update_variables(bool in_flight) } var.value = NULL; - var.key = "neon_enhancement_enable"; + var.key = "pcsx_rearmed_neon_enhancement_enable"; if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) || var.value) { @@ -1015,7 +1015,7 @@ static void update_variables(bool in_flight) } var.value = NULL; - var.key = "neon_enhancement_no_main"; + var.key = "pcsx_rearmed_neon_enhancement_no_main"; if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) || var.value) { -- cgit v1.2.3 From 4726dba005562cbaf69cc8e10ef7102184c4a089 Mon Sep 17 00:00:00 2001 From: notaz Date: Sat, 6 Dec 2014 18:26:16 +0200 Subject: psxmem: remove hard requirement for a mapping not all platforms have 1f800000 free not all mmap implementations use the addr hint.. --- libpcsxcore/new_dynarec/assem_arm.c | 14 ++++++++++---- libpcsxcore/psxmem.c | 4 ++-- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/libpcsxcore/new_dynarec/assem_arm.c b/libpcsxcore/new_dynarec/assem_arm.c index 45edd65..9ee832e 100644 --- a/libpcsxcore/new_dynarec/assem_arm.c +++ b/libpcsxcore/new_dynarec/assem_arm.c @@ -3999,10 +3999,16 @@ static int emit_fastpath_cmp_jump(int i,int addr,int *addr_reg_override) type=0; } else if(type==MTYPE_1F80) { // scratchpad - emit_addimm(addr,-0x1f800000,HOST_TEMPREG); - emit_cmpimm(HOST_TEMPREG,0x1000); - jaddr=(int)out; - emit_jc(0); + if (psxH == (void *)0x1f800000) { + emit_addimm(addr,-0x1f800000,HOST_TEMPREG); + emit_cmpimm(HOST_TEMPREG,0x1000); + jaddr=(int)out; + emit_jc(0); + } + else { + // do usual RAM check, jump will go to the right handler + type=0; + } } #endif diff --git a/libpcsxcore/psxmem.c b/libpcsxcore/psxmem.c index 2ca5dd5..7001744 100644 --- a/libpcsxcore/psxmem.c +++ b/libpcsxcore/psxmem.c @@ -150,11 +150,11 @@ int psxMemInit() { } psxP = &psxM[0x200000]; - psxH = psxMap(0x1f800000, 0x10000, 1, MAP_TAG_OTHER); + psxH = psxMap(0x1f800000, 0x10000, 0, MAP_TAG_OTHER); psxR = psxMap(0x1fc00000, 0x80000, 0, MAP_TAG_OTHER); if (psxMemRLUT == NULL || psxMemWLUT == NULL || - psxR == NULL || psxP == NULL || psxH != (void *)0x1f800000) { + psxR == NULL || psxP == NULL || psxH == NULL) { SysMessage(_("Error allocating memory!")); psxMemShutdown(); return -1; -- cgit v1.2.3 From d515eaa2e43d87a2fe7d54b7f7b30174631f2d18 Mon Sep 17 00:00:00 2001 From: notaz Date: Sat, 6 Dec 2014 19:14:34 +0200 Subject: misc: don't succeed on trash input --- libpcsxcore/misc.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/libpcsxcore/misc.c b/libpcsxcore/misc.c index 874624d..905f142 100644 --- a/libpcsxcore/misc.c +++ b/libpcsxcore/misc.c @@ -109,6 +109,7 @@ void mmssdd( char *b, char *p ) int GetCdromFile(u8 *mdir, u8 *time, char *filename) { struct iso_directory_record *dir; + int retval = -1; u8 ddir[4096]; u8 *buf; int i; @@ -138,11 +139,12 @@ int GetCdromFile(u8 *mdir, u8 *time, char *filename) { } else { if (!strnicmp((char *)&dir->name[0], filename, strlen(filename))) { mmssdd(dir->extent, (char *)time); + retval = 0; break; } } } - return 0; + return retval; } static const unsigned int gpu_ctl_def[] = { -- cgit v1.2.3 From 52990dd97f8a7abbe5b24d3405f3bcc3ba426e5d Mon Sep 17 00:00:00 2001 From: notaz Date: Sat, 6 Dec 2014 22:52:05 +0200 Subject: misc: length is unsigned --- libpcsxcore/misc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libpcsxcore/misc.c b/libpcsxcore/misc.c index 905f142..a27f60f 100644 --- a/libpcsxcore/misc.c +++ b/libpcsxcore/misc.c @@ -123,7 +123,7 @@ int GetCdromFile(u8 *mdir, u8 *time, char *filename) { if (dir->length[0] == 0) { return -1; } - i += dir->length[0]; + i += (u8)dir->length[0]; if (dir->flags[0] & 0x2) { // it's a dir if (!strnicmp((char *)&dir->name[0], filename, dir->name_len[0])) { -- cgit v1.2.3 From 3a92bf0b7a2d929f53ae69cf761721c136f9036d Mon Sep 17 00:00:00 2001 From: twinaphex Date: Sat, 13 Dec 2014 05:53:54 +0100 Subject: Add mman wrapper for Win32 and use it for PCSX ReARmed libretro Win32 --- Makefile | 4 ++ Makefile.libretro | 4 ++ libpcsxcore/memmap.h | 60 ++++++++++++++++ libpcsxcore/memmap_win32.c | 173 +++++++++++++++++++++++++++++++++++++++++++++ libpcsxcore/psxmem.c | 5 ++ 5 files changed, 246 insertions(+) create mode 100644 libpcsxcore/memmap.h create mode 100644 libpcsxcore/memmap_win32.c diff --git a/Makefile b/Makefile index 6187958..9568d0e 100644 --- a/Makefile +++ b/Makefile @@ -195,6 +195,10 @@ endif ifeq "$(PLATFORM)" "libretro" OBJS += frontend/libretro.o CFLAGS += -DFRONTEND_SUPPORTS_RGB565 + +ifeq ($(MMAP_WIN32),1) +OBJS += libpcsxcore/memmap_win32.o +endif endif ifeq "$(USE_PLUGIN_LIB)" "1" diff --git a/Makefile.libretro b/Makefile.libretro index b92cea4..6d37652 100644 --- a/Makefile.libretro +++ b/Makefile.libretro @@ -1,5 +1,8 @@ # Makefile for PCSX ReARMed (libretro) +DEBUG=1 +MMAP_WIN32=0 + ifeq ($(platform),) platform = unix ifeq ($(shell uname -a),) @@ -147,6 +150,7 @@ else CFLAGS += -D__WIN32__ -D__WIN32_LIBRETRO__ BUILTIN_GPU = neon CFLAGS += -DNEON_PC + MMAP_WIN32=1 endif CFLAGS += -fPIC diff --git a/libpcsxcore/memmap.h b/libpcsxcore/memmap.h new file mode 100644 index 0000000..e80d720 --- /dev/null +++ b/libpcsxcore/memmap.h @@ -0,0 +1,60 @@ +#ifndef _MEMMAP_H +#define _MEMMAP_H + +#ifdef HAVE_MMAP + +#ifdef _WIN32 + +#ifndef _WIN32_WINNT // Allow use of features specific to Windows XP or later. +#define _WIN32_WINNT 0x0501 // Change this to the appropriate value to target other versions of Windows. +#endif + +/* All the headers include this file. */ +#ifndef _MSC_VER +#include <_mingw.h> +#endif + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define PROT_NONE 0 +#define PROT_READ 1 +#define PROT_WRITE 2 +#define PROT_EXEC 4 + +#define MAP_FILE 0 +#define MAP_SHARED 1 +#define MAP_PRIVATE 2 +#define MAP_TYPE 0xf +#define MAP_FIXED 0x10 +#define MAP_ANONYMOUS 0x20 +#define MAP_ANON MAP_ANONYMOUS + +#define MAP_FAILED ((void *)-1) + +/* Flags for msync. */ +#define MS_ASYNC 1 +#define MS_SYNC 2 +#define MS_INVALIDATE 4 + +void* mmap(void *addr, size_t len, int prot, int flags, int fildes, off_t off); +int munmap(void *addr, size_t len); +int mprotect(void *addr, size_t len, int prot); +int msync(void *addr, size_t len, int flags); +int mlock(const void *addr, size_t len); +int munlock(const void *addr, size_t len); + +#ifdef __cplusplus +}; +#endif + +#else +#include +#endif + +#endif + +#endif diff --git a/libpcsxcore/memmap_win32.c b/libpcsxcore/memmap_win32.c new file mode 100644 index 0000000..f4dbdd6 --- /dev/null +++ b/libpcsxcore/memmap_win32.c @@ -0,0 +1,173 @@ +#include +#include +#include + +#include "mman.h" + +#ifndef FILE_MAP_EXECUTE +#define FILE_MAP_EXECUTE 0x0020 +#endif /* FILE_MAP_EXECUTE */ + +static int __map_mman_error(const DWORD err, const int deferr) +{ + if (err == 0) + return 0; + /* TODO: implement */ + return err; +} + +static DWORD __map_mmap_prot_page(const int prot) +{ + DWORD protect = 0; + + if (prot == PROT_NONE) + return 0; + + if ((prot & PROT_EXEC) != 0) + protect = ((prot & PROT_WRITE) != 0) ? + PAGE_EXECUTE_READWRITE : PAGE_EXECUTE_READ; + else + protect = ((prot & PROT_WRITE) != 0) ? + PAGE_READWRITE : PAGE_READONLY; + + return protect; +} + +static DWORD __map_mmap_prot_file(const int prot) +{ + DWORD desiredAccess = 0; + + if (prot == PROT_NONE) + return 0; + + if ((prot & PROT_READ) != 0) + desiredAccess |= FILE_MAP_READ; + if ((prot & PROT_WRITE) != 0) + desiredAccess |= FILE_MAP_WRITE; + if ((prot & PROT_EXEC) != 0) + desiredAccess |= FILE_MAP_EXECUTE; + + return desiredAccess; +} + +void* mmap(void *addr, size_t len, int prot, int flags, int fildes, off_t off) +{ + HANDLE fm, h; + + void * map = MAP_FAILED; + +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable: 4293) +#endif + + const DWORD dwFileOffsetLow = (sizeof(off_t) <= sizeof(DWORD)) ? + (DWORD)off : (DWORD)(off & 0xFFFFFFFFL); + const DWORD dwFileOffsetHigh = (sizeof(off_t) <= sizeof(DWORD)) ? + (DWORD)0 : (DWORD)((off >> 32) & 0xFFFFFFFFL); + const DWORD protect = __map_mmap_prot_page(prot); + const DWORD desiredAccess = __map_mmap_prot_file(prot); + + const off_t maxSize = off + (off_t)len; + + const DWORD dwMaxSizeLow = (sizeof(off_t) <= sizeof(DWORD)) ? + (DWORD)maxSize : (DWORD)(maxSize & 0xFFFFFFFFL); + const DWORD dwMaxSizeHigh = (sizeof(off_t) <= sizeof(DWORD)) ? + (DWORD)0 : (DWORD)((maxSize >> 32) & 0xFFFFFFFFL); + +#ifdef _MSC_VER +#pragma warning(pop) +#endif + + errno = 0; + + if (len == 0 + /* Unsupported flag combinations */ + || (flags & MAP_FIXED) != 0 + /* Usupported protection combinations */ + || prot == PROT_EXEC) + { + errno = EINVAL; + return MAP_FAILED; + } + + h = ((flags & MAP_ANONYMOUS) == 0) ? + (HANDLE)_get_osfhandle(fildes) : INVALID_HANDLE_VALUE; + + if ((flags & MAP_ANONYMOUS) == 0 && h == INVALID_HANDLE_VALUE) + { + errno = EBADF; + return MAP_FAILED; + } + + fm = CreateFileMapping(h, NULL, protect, dwMaxSizeHigh, dwMaxSizeLow, NULL); + + if (!fm) + goto error; + + map = MapViewOfFile(fm, desiredAccess, dwFileOffsetHigh, dwFileOffsetLow, len); + + CloseHandle(fm); + + if (!map) + goto error; + + return map; +error: + errno = __map_mman_error(GetLastError(), EPERM); + return MAP_FAILED; +} + +int munmap(void *addr, size_t len) +{ + if (UnmapViewOfFile(addr)) + return 0; + + errno = __map_mman_error(GetLastError(), EPERM); + + return -1; +} + +int mprotect(void *addr, size_t len, int prot) +{ + DWORD newProtect = __map_mmap_prot_page(prot); + DWORD oldProtect = 0; + + if (VirtualProtect(addr, len, newProtect, &oldProtect)) + return 0; + + errno = __map_mman_error(GetLastError(), EPERM); + + return -1; +} + +int msync(void *addr, size_t len, int flags) +{ + if (FlushViewOfFile(addr, len)) + return 0; + + errno = __map_mman_error(GetLastError(), EPERM); + + return -1; +} + +int mlock(const void *addr, size_t len) +{ + if (VirtualLock((LPVOID)addr, len)) + return 0; + + errno = __map_mman_error(GetLastError(), EPERM); + + return -1; +} + +int munlock(const void *addr, size_t len) +{ + if (VirtualUnlock((LPVOID)addr, len)) + return 0; + + errno = __map_mman_error(GetLastError(), EPERM); + + return -1; +} + diff --git a/libpcsxcore/psxmem.c b/libpcsxcore/psxmem.c index 7001744..259128d 100644 --- a/libpcsxcore/psxmem.c +++ b/libpcsxcore/psxmem.c @@ -28,7 +28,12 @@ #include "r3000a.h" #include "psxhw.h" #include "debug.h" + +#ifdef __LIBRETRO__ +#include "memmap.h" +#else #include +#endif #ifndef MAP_ANONYMOUS #define MAP_ANONYMOUS MAP_ANON -- cgit v1.2.3 From 624241c2572665e128d2566aaa4cdd4f0d55ab2f Mon Sep 17 00:00:00 2001 From: twinaphex Date: Sat, 13 Dec 2014 05:54:35 +0100 Subject: Just use memmap.h header include in general --- libpcsxcore/psxmem.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/libpcsxcore/psxmem.c b/libpcsxcore/psxmem.c index 259128d..86da68c 100644 --- a/libpcsxcore/psxmem.c +++ b/libpcsxcore/psxmem.c @@ -29,11 +29,7 @@ #include "psxhw.h" #include "debug.h" -#ifdef __LIBRETRO__ #include "memmap.h" -#else -#include -#endif #ifndef MAP_ANONYMOUS #define MAP_ANONYMOUS MAP_ANON -- cgit v1.2.3 From 30322c7d106503926208ebeeed60ca04391d0669 Mon Sep 17 00:00:00 2001 From: sergiobenrocha2 Date: Sun, 14 Dec 2014 01:57:51 -0200 Subject: Cleanup Makefile.libretro. --- Makefile.libretro | 258 ++++++++++++++++++++++++++++++------------------------ 1 file changed, 142 insertions(+), 116 deletions(-) diff --git a/Makefile.libretro b/Makefile.libretro index 6d37652..6a90717 100644 --- a/Makefile.libretro +++ b/Makefile.libretro @@ -4,16 +4,16 @@ DEBUG=1 MMAP_WIN32=0 ifeq ($(platform),) -platform = unix -ifeq ($(shell uname -a),) - platform = win -else ifneq ($(findstring MINGW,$(shell uname -a)),) - platform = win -else ifneq ($(findstring Darwin,$(shell uname -a)),) - platform = osx -else ifneq ($(findstring win,$(shell uname -a)),) - platform = win -endif + platform = unix + ifeq ($(shell uname -a),) + platform = win + else ifneq ($(findstring MINGW,$(shell uname -a)),) + platform = win + else ifneq ($(findstring Darwin,$(shell uname -a)),) + platform = osx + else ifneq ($(findstring win,$(shell uname -a)),) + platform = win + endif endif CC ?= gcc @@ -24,139 +24,165 @@ CFLAGS ?= TARGET_NAME := pcsx_rearmed +# Unix ifeq ($(platform), unix) - TARGET := $(TARGET_NAME)_libretro.so - fpic := -fPIC - SHARED := -shared -Wl,--version-script=libretro/link.T - BUILTIN_GPU = neon + TARGET := $(TARGET_NAME)_libretro.so + fpic := -fPIC + SHARED := -shared -Wl,--version-script=libretro/link.T + BUILTIN_GPU = neon CFLAGS += -DNEON_PC + +# OS X else ifeq ($(platform), osx) - TARGET := $(TARGET_NAME)_libretro.dylib - fpic := -fPIC - SHARED := -dynamiclib - BUILTIN_GPU = neon + TARGET := $(TARGET_NAME)_libretro.dylib + fpic := -fPIC + SHARED := -dynamiclib + BUILTIN_GPU = neon CFLAGS += -DNEON_PC - OSXVER = `sw_vers -productVersion | cut -d. -f 2` - OSX_LT_MAVERICKS = `(( $(OSXVER) <= 9)) && echo "YES"` -ifeq ($(OSX_LT_MAVERICKS),"YES") - fpic += -mmacosx-version-min=10.5 -endif + OSXVER = `sw_vers -productVersion | cut -d. -f 2` + OSX_LT_MAVERICKS = `(( $(OSXVER) <= 9)) && echo "YES"` + ifeq ($(OSX_LT_MAVERICKS),"YES") + fpic += -mmacosx-version-min=10.5 + endif + +# iOS else ifeq ($(platform), ios) -ARCH := arm - TARGET := $(TARGET_NAME)_libretro_ios.dylib - fpic := -fPIC - SHARED := -dynamiclib + ARCH := arm + TARGET := $(TARGET_NAME)_libretro_ios.dylib + fpic := -fPIC + SHARED := -dynamiclib -ifeq ($(IOSSDK),) - IOSSDK := $(shell xcrun -sdk iphoneos -show-sdk-path) -endif + ifeq ($(IOSSDK),) + IOSSDK := $(shell xcrun -sdk iphoneos -show-sdk-path) + endif - CC = clang -arch armv7 -isysroot $(IOSSDK) - CXX = clang++ -arch armv7 -isysroot $(IOSSDK) - CC_AS = perl ./tools/gas-preprocessor.pl $(CC) - CFLAGS += -mcpu=cortex-a8 -mtune=cortex-a8 -mfpu=neon -marm - ASFLAGS += -mcpu=cortex-a8 -mtune=cortex-a8 -mfpu=neon - HAVE_NEON = 1 - BUILTIN_GPU = neon - USE_DYNAREC = 1 - CFLAGS += -DIOS - OSXVER = `sw_vers -productVersion | cut -d. -f 2` - OSX_LT_MAVERICKS = `(( $(OSXVER) <= 9)) && echo "YES"` -ifeq ($(OSX_LT_MAVERICKS),"YES") - CC += -miphoneos-version-min=5.0 - CXX += -miphoneos-version-min=5.0 - CC_AS += -miphoneos-version-min=5.0 - CFLAGS += -miphoneos-version-min=5.0 -endif + CC = clang -arch armv7 -isysroot $(IOSSDK) + CXX = clang++ -arch armv7 -isysroot $(IOSSDK) + CC_AS = perl ./tools/gas-preprocessor.pl $(CC) + CFLAGS += -mcpu=cortex-a8 -mtune=cortex-a8 -mfpu=neon -marm + ASFLAGS += -mcpu=cortex-a8 -mtune=cortex-a8 -mfpu=neon + HAVE_NEON = 1 + BUILTIN_GPU = neon + USE_DYNAREC = 1 + CFLAGS += -DIOS + OSXVER = `sw_vers -productVersion | cut -d. -f 2` + OSX_LT_MAVERICKS = `(( $(OSXVER) <= 9)) && echo "YES"` + ifeq ($(OSX_LT_MAVERICKS),"YES") + CC += -miphoneos-version-min=5.0 + CXX += -miphoneos-version-min=5.0 + CC_AS += -miphoneos-version-min=5.0 + CFLAGS += -miphoneos-version-min=5.0 + endif + +# PS3 else ifeq ($(platform), ps3) - TARGET := $(TARGET_NAME)_libretro_ps3.a - CC = $(CELL_SDK)/host-win32/ppu/bin/ppu-lv2-gcc.exe - AR = $(CELL_SDK)/host-win32/ppu/bin/ppu-lv2-ar.exe - CFLAGS += -DBLARGG_BIG_ENDIAN=1 -D__ppc__ + TARGET := $(TARGET_NAME)_libretro_ps3.a + CC = $(CELL_SDK)/host-win32/ppu/bin/ppu-lv2-gcc.exe + AR = $(CELL_SDK)/host-win32/ppu/bin/ppu-lv2-ar.exe + CFLAGS += -DBLARGG_BIG_ENDIAN=1 -D__ppc__ + +# sncps3 else ifeq ($(platform), sncps3) - TARGET := $(TARGET_NAME)_libretro_ps3.a - CC = $(CELL_SDK)/host-win32/sn/bin/ps3ppusnc.exe - AR = $(CELL_SDK)/host-win32/sn/bin/ps3snarl.exe - CFLAGS += -DBLARGG_BIG_ENDIAN=1 -D__ppc__ + TARGET := $(TARGET_NAME)_libretro_ps3.a + CC = $(CELL_SDK)/host-win32/sn/bin/ps3ppusnc.exe + AR = $(CELL_SDK)/host-win32/sn/bin/ps3snarl.exe + CFLAGS += -DBLARGG_BIG_ENDIAN=1 -D__ppc__ + +# Lightweight PS3 Homebrew SDK else ifeq ($(platform), psl1ght) - TARGET := $(TARGET_NAME)_libretro_psl1ght.a - CC = $(PS3DEV)/ppu/bin/ppu-gcc$(EXE_EXT) - AR = $(PS3DEV)/ppu/bin/ppu-ar$(EXE_EXT) - CFLAGS += -DBLARGG_BIG_ENDIAN=1 -D__ppc__ + TARGET := $(TARGET_NAME)_libretro_psl1ght.a + CC = $(PS3DEV)/ppu/bin/ppu-gcc$(EXE_EXT) + AR = $(PS3DEV)/ppu/bin/ppu-ar$(EXE_EXT) + CFLAGS += -DBLARGG_BIG_ENDIAN=1 -D__ppc__ + +# PSP else ifeq ($(platform), psp1) TARGET := $(TARGET_NAME)_libretro_psp1.a CC = psp-gcc$(EXE_EXT) AR = psp-ar$(EXE_EXT) CFLAGS += -DPSP -G0 + +# Xbox 360 else ifeq ($(platform), xenon) - TARGET := $(TARGET_NAME)_libretro_xenon360.a - CC = xenon-gcc$(EXE_EXT) - AR = xenon-ar$(EXE_EXT) - CFLAGS += -D__LIBXENON__ -m32 -D__ppc__ + TARGET := $(TARGET_NAME)_libretro_xenon360.a + CC = xenon-gcc$(EXE_EXT) + AR = xenon-ar$(EXE_EXT) + CFLAGS += -D__LIBXENON__ -m32 -D__ppc__ + +# Nintendo Game Cube else ifeq ($(platform), ngc) - TARGET := $(TARGET_NAME)_libretro_ngc.a - CC = $(DEVKITPPC)/bin/powerpc-eabi-gcc$(EXE_EXT) - AR = $(DEVKITPPC)/bin/powerpc-eabi-ar$(EXE_EXT) - CFLAGS += -DGEKKO -DHW_DOL -mrvl -mcpu=750 -meabi -mhard-float -DBLARGG_BIG_ENDIAN=1 -D__ppc__ + TARGET := $(TARGET_NAME)_libretro_ngc.a + CC = $(DEVKITPPC)/bin/powerpc-eabi-gcc$(EXE_EXT) + AR = $(DEVKITPPC)/bin/powerpc-eabi-ar$(EXE_EXT) + CFLAGS += -DGEKKO -DHW_DOL -mrvl -mcpu=750 -meabi -mhard-float -DBLARGG_BIG_ENDIAN=1 -D__ppc__ + +# Nintendo Wii else ifeq ($(platform), wii) - TARGET := libretro_$(TARGET_NAME)_wii.a - CC = $(DEVKITPPC)/bin/powerpc-eabi-gcc$(EXE_EXT) - AR = $(DEVKITPPC)/bin/powerpc-eabi-ar$(EXE_EXT) - CFLAGS += -DGEKKO -DHW_RVL -mrvl -mcpu=750 -meabi -mhard-float -DBLARGG_BIG_ENDIAN=1 -D__ppc__ + TARGET := libretro_$(TARGET_NAME)_wii.a + CC = $(DEVKITPPC)/bin/powerpc-eabi-gcc$(EXE_EXT) + AR = $(DEVKITPPC)/bin/powerpc-eabi-ar$(EXE_EXT) + CFLAGS += -DGEKKO -DHW_RVL -mrvl -mcpu=750 -meabi -mhard-float -DBLARGG_BIG_ENDIAN=1 -D__ppc__ + +# QNX else ifeq ($(platform), qnx) - TARGET := $(TARGET_NAME)_libretro_qnx.so - CC = qcc -Vgcc_ntoarmv7le - CC_AS = $(CC) - HAVE_NEON = 1 - USE_DYNAREC = 1 - DRC_CACHE_BASE = 0 - BUILTIN_GPU = neon - ARCH = arm - CFLAGS += -DBASE_ADDR_FIXED=0 -D__BLACKBERRY_QNX__ -marm -mcpu=cortex-a9 -mtune=cortex-a9 -mfpu=neon -mfloat-abi=softfp - ASFLAGS += -mcpu=cortex-a9 -mfpu=neon -mfloat-abi=softfp + TARGET := $(TARGET_NAME)_libretro_qnx.so + CC = qcc -Vgcc_ntoarmv7le + CC_AS = $(CC) + HAVE_NEON = 1 + USE_DYNAREC = 1 + DRC_CACHE_BASE = 0 + BUILTIN_GPU = neon + ARCH = arm + CFLAGS += -DBASE_ADDR_FIXED=0 -D__BLACKBERRY_QNX__ -marm -mcpu=cortex-a9 -mtune=cortex-a9 -mfpu=neon -mfloat-abi=softfp + ASFLAGS += -mcpu=cortex-a9 -mfpu=neon -mfloat-abi=softfp + +# ARM else ifneq (,$(findstring armv,$(platform))) - TARGET := $(TARGET_NAME)_libretro.so - SHARED := -shared -Wl,--no-undefined - DRC_CACHE_BASE = 0 -ifneq (,$(findstring cortexa8,$(platform))) - CFLAGS += -marm -mcpu=cortex-a8 - ASFLAGS += -mcpu=cortex-a8 -else ifneq (,$(findstring cortexa9,$(platform))) - CFLAGS += -marm -mcpu=cortex-a9 - ASFLAGS += -mcpu=cortex-a9 -endif - CFLAGS += -marm -ifneq (,$(findstring neon,$(platform))) - CFLAGS += -mfpu=neon - ASFLAGS += -mfpu=neon - HAVE_NEON = 1 - BUILTIN_GPU = neon -endif -ifneq (,$(findstring softfloat,$(platform))) - CFLAGS += -mfloat-abi=softfp - ASFLAGS += -mfloat-abi=softfp -else ifneq (,$(findstring hardfloat,$(platform))) - CFLAGS += -mfloat-abi=hard - ASFLAGS += -mfloat-abi=hard -endif - ARCH = arm - USE_DYNAREC = 1 + TARGET := $(TARGET_NAME)_libretro.so + SHARED := -shared -Wl,--no-undefined + DRC_CACHE_BASE = 0 + ifneq (,$(findstring cortexa8,$(platform))) + CFLAGS += -marm -mcpu=cortex-a8 + ASFLAGS += -mcpu=cortex-a8 + else ifneq (,$(findstring cortexa9,$(platform))) + CFLAGS += -marm -mcpu=cortex-a9 + ASFLAGS += -mcpu=cortex-a9 + endif + CFLAGS += -marm + ifneq (,$(findstring neon,$(platform))) + CFLAGS += -mfpu=neon + ASFLAGS += -mfpu=neon + HAVE_NEON = 1 + BUILTIN_GPU = neon + endif + ifneq (,$(findstring softfloat,$(platform))) + CFLAGS += -mfloat-abi=softfp + ASFLAGS += -mfloat-abi=softfp + else ifneq (,$(findstring hardfloat,$(platform))) + CFLAGS += -mfloat-abi=hard + ASFLAGS += -mfloat-abi=hard + endif + ARCH = arm + USE_DYNAREC = 1 + +# Windows else - TARGET := $(TARGET_NAME)_libretro.dll - CC = gcc - fpic := -fPIC - LD_FLAGS := -fPIC - SHARED := -shared -static-libgcc -static-libstdc++ -s -Wl,--version-script=libretro/link.T - CFLAGS += -D__WIN32__ -D__WIN32_LIBRETRO__ - BUILTIN_GPU = neon + TARGET := $(TARGET_NAME)_libretro.dll + CC = gcc + fpic := -fPIC + LD_FLAGS := -fPIC + SHARED := -shared -static-libgcc -static-libstdc++ -s -Wl,--version-script=libretro/link.T + CFLAGS += -D__WIN32__ -D__WIN32_LIBRETRO__ + BUILTIN_GPU = neon CFLAGS += -DNEON_PC MMAP_WIN32=1 + endif CFLAGS += -fPIC ifneq ($(platform),qnx) - LDLIBS += -lpthread - MAIN_LDLIBS += -ldl + LDLIBS += -lpthread + MAIN_LDLIBS += -ldl endif MAIN_LDFLAGS += -shared MAIN_LDLIBS += -lm -lz -- cgit v1.2.3 From 3e5b01fcef8ef20dacca45ea7a7b0c461e6bd666 Mon Sep 17 00:00:00 2001 From: twinaphex Date: Mon, 15 Dec 2014 21:10:07 +0100 Subject: Get rid of HAVE_MMAP ifdef --- libpcsxcore/memmap.h | 4 ---- 1 file changed, 4 deletions(-) diff --git a/libpcsxcore/memmap.h b/libpcsxcore/memmap.h index e80d720..ad56f04 100644 --- a/libpcsxcore/memmap.h +++ b/libpcsxcore/memmap.h @@ -1,8 +1,6 @@ #ifndef _MEMMAP_H #define _MEMMAP_H -#ifdef HAVE_MMAP - #ifdef _WIN32 #ifndef _WIN32_WINNT // Allow use of features specific to Windows XP or later. @@ -56,5 +54,3 @@ int munlock(const void *addr, size_t len); #endif #endif - -#endif -- cgit v1.2.3