aboutsummaryrefslogtreecommitdiff
path: root/frontend
diff options
context:
space:
mode:
Diffstat (limited to 'frontend')
-rwxr-xr-xfrontend/320240/caanoo.gpe23
-rw-r--r--frontend/320240/haptic_s.cfg3
-rw-r--r--frontend/320240/haptic_w.cfg3
-rw-r--r--frontend/320240/pcsx26.pngbin4763 -> 0 bytes
-rw-r--r--frontend/320240/pcsx_rearmed.ini6
-rw-r--r--frontend/320240/pcsxb.pngbin24784 -> 0 bytes
-rw-r--r--frontend/320240/pollux_set.c389
-rw-r--r--frontend/320240/skin/background.pngbin36069 -> 0 bytes
-rw-r--r--frontend/320240/skin/font.pngbin3185 -> 0 bytes
-rw-r--r--frontend/320240/skin/readme.txt8
-rw-r--r--frontend/320240/skin/selector.pngbin261 -> 0 bytes
-rw-r--r--frontend/320240/skin/skin.txt4
-rw-r--r--frontend/320240/ui_gp2x.h15
-rw-r--r--frontend/3ds/3ds_utils.h66
-rw-r--r--frontend/3ds/pthread.h56
-rw-r--r--frontend/3ds/sys/mman.h107
-rw-r--r--frontend/3ds/zconf.h511
-rw-r--r--frontend/3ds/zlib.h1768
-rw-r--r--frontend/cspace.c50
m---------frontend/libpicofe0
-rw-r--r--frontend/libretro.c1186
-rwxr-xr-xfrontend/libretro.h1510
-rw-r--r--frontend/link.T5
-rw-r--r--frontend/main.c25
-rw-r--r--frontend/menu.c15
-rw-r--r--frontend/pandora/pcsx.pngbin7981 -> 0 bytes
-rw-r--r--frontend/pandora/pcsx.pxml.templ42
-rwxr-xr-xfrontend/pandora/pcsx.sh24
-rw-r--r--frontend/pandora/picorestore.c109
-rw-r--r--frontend/pandora/skin/background.pngbin183772 -> 0 bytes
-rw-r--r--frontend/pandora/skin/font.pngbin11264 -> 0 bytes
-rw-r--r--frontend/pandora/skin/readme.txt8
-rw-r--r--frontend/pandora/skin/selector.pngbin386 -> 0 bytes
-rw-r--r--frontend/pandora/skin/skin.txt4
-rw-r--r--frontend/pandora/ui_feat.h16
-rw-r--r--frontend/plugin.c51
-rw-r--r--frontend/plugin_lib.c16
-rw-r--r--frontend/plugin_lib.h11
-rw-r--r--frontend/vita/retro_inline.h39
-rw-r--r--frontend/vita/sys/mman.h69
m---------frontend/warm0
41 files changed, 4853 insertions, 1286 deletions
diff --git a/frontend/320240/caanoo.gpe b/frontend/320240/caanoo.gpe
deleted file mode 100755
index 9d6154a..0000000
--- a/frontend/320240/caanoo.gpe
+++ /dev/null
@@ -1,23 +0,0 @@
-#!/bin/sh
-
-# Wiz's timings are already good, apply this for Caanoo
-if [ -e /dev/accel ]; then
- ./pollux_set "ram_timings=3,9,4,1,1,1,1"
-fi
-
-# the sync mount causes problems when writing saves,
-# probably due to many write calls, so have to get rid of it
-if grep mmcblk /proc/mounts | grep -q '\<sync\>'; then
- oldmount=`grep mmcblk /proc/mounts | grep '\<sync\>' | awk '{print $4}'`
- mount /dev/mmcblk0p1 /mnt/sd/ -o remount,dirsync,noatime
-fi
-
-./pcsx "$@"
-sync
-
-if [ -n "$oldmount" ]; then
- mount /dev/mmcblk0p1 /mnt/sd/ -o remount,$oldmount
-fi
-
-cd /usr/gp2x
-exec ./gp2xmenu
diff --git a/frontend/320240/haptic_s.cfg b/frontend/320240/haptic_s.cfg
deleted file mode 100644
index 624056d..0000000
--- a/frontend/320240/haptic_s.cfg
+++ /dev/null
@@ -1,3 +0,0 @@
-0 126
-100 -126
-115 0
diff --git a/frontend/320240/haptic_w.cfg b/frontend/320240/haptic_w.cfg
deleted file mode 100644
index 3585a71..0000000
--- a/frontend/320240/haptic_w.cfg
+++ /dev/null
@@ -1,3 +0,0 @@
-0 54
-100 -126
-105 0
diff --git a/frontend/320240/pcsx26.png b/frontend/320240/pcsx26.png
deleted file mode 100644
index ed220a0..0000000
--- a/frontend/320240/pcsx26.png
+++ /dev/null
Binary files differ
diff --git a/frontend/320240/pcsx_rearmed.ini b/frontend/320240/pcsx_rearmed.ini
deleted file mode 100644
index b15497f..0000000
--- a/frontend/320240/pcsx_rearmed.ini
+++ /dev/null
@@ -1,6 +0,0 @@
-[info]
-name="PCSX ReARMed"
-icon="/pcsx_rearmed/pcsx26.png"
-path="/pcsx_rearmed/pcsx.gpe"
-title="/pcsx_rearmed/pcsxb.png"
-group="GAMES"
diff --git a/frontend/320240/pcsxb.png b/frontend/320240/pcsxb.png
deleted file mode 100644
index ff5a48a..0000000
--- a/frontend/320240/pcsxb.png
+++ /dev/null
Binary files differ
diff --git a/frontend/320240/pollux_set.c b/frontend/320240/pollux_set.c
deleted file mode 100644
index f49e777..0000000
--- a/frontend/320240/pollux_set.c
+++ /dev/null
@@ -1,389 +0,0 @@
-/*
- * quick tool to set various timings for Wiz
- *
- * Copyright (c) Gražvydas "notaz" Ignotas, 2009
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * * Neither the name of the organization nor the
- * names of its contributors may be used to endorse or promote products
- * derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
- * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * HTOTAL: X VTOTAL: 341
- * HSWIDTH: 1 VSWIDTH: 0
- * HASTART: 37 VASTART: 17
- * HAEND: 277 VAEND: 337
- *
- * 120Hz
- * pcd 8, 447: + 594us
- * pcd 9, 397: + 36us
- * pcd 10, 357: - 523us
- * pcd 11, 325: +1153us
- *
- * 'lcd_timings=397,1,37,277,341,0,17,337;dpc_clkdiv0=9'
- * 'ram_timings=2,9,4,1,1,1,1'
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-//#include "pollux_set.h"
-#define BINARY
-
-/* parse stuff */
-static int parse_lcd_timings(const char *str, void *data)
-{
- int *lcd_timings = data;
- const char *p = str;
- int ret, c;
- ret = sscanf(str, "%d,%d,%d,%d,%d,%d,%d,%d",
- &lcd_timings[0], &lcd_timings[1], &lcd_timings[2], &lcd_timings[3],
- &lcd_timings[4], &lcd_timings[5], &lcd_timings[6], &lcd_timings[7]);
- if (ret != 8)
- return -1;
- /* skip seven commas */
- for (c = 0; c < 7 && *p != 0; p++)
- if (*p == ',')
- c++;
- if (c != 7)
- return -1;
- /* skip last number */
- while ('0' <= *p && *p <= '9')
- p++;
-
- return p - str;
-}
-
-static int parse_ram_timings(const char *str, void *data)
-{
- int *ram_timings = data;
- const char *p = str;
- int ret, c;
- float cas;
-
- ret = sscanf(p, "%f,%d,%d,%d,%d,%d,%d",
- &cas, &ram_timings[1], &ram_timings[2], &ram_timings[3],
- &ram_timings[4], &ram_timings[5], &ram_timings[6]);
- if (ret != 7)
- return -1;
- if (cas == 2)
- ram_timings[0] = 1;
- else if (cas == 2.5)
- ram_timings[0] = 2;
- else if (cas == 3)
- ram_timings[0] = 3;
- else
- return -1;
- for (c = 0; c < 6 && *p != 0; p++)
- if (*p == ',')
- c++;
- if (c != 6)
- return -1;
- while ('0' <= *p && *p <= '9')
- p++;
-
- return p - str;
-}
-
-static int parse_decimal(const char *str, void *data)
-{
- char *ep;
-
- *(int *)data = strtoul(str, &ep, 10);
- if (ep == str)
- return -1;
-
- return ep - str;
-}
-
-/* validate and apply stuff */
-static int apply_lcd_timings(volatile unsigned short *memregs, void *data)
-{
- int *lcd_timings = data;
- int i;
-
- for (i = 0; i < 8; i++) {
- if (lcd_timings[i] & ~0xffff) {
- fprintf(stderr, "pollux_set: invalid lcd timing %d: %d\n", i, lcd_timings[i]);
- return -1;
- }
- }
-
- for (i = 0; i < 8; i++)
- memregs[(0x307c>>1) + i] = lcd_timings[i];
-
- return 0;
-}
-
-static const struct {
- signed char adj; /* how to adjust value passed by user */
- signed short min; /* range of */
- signed short max; /* allowed values (inclusive) */
-}
-ram_ranges[] = {
- { 0, 1, 3 }, /* cas (cl) */
- { -2, 0, 15 }, /* trc */
- { -2, 0, 15 }, /* tras */
- { 0, 0, 15 }, /* twr */
- { 0, 0, 15 }, /* tmrd */
- { 0, 0, 15 }, /* trp */
- { 0, 0, 15 }, /* trcd */
-};
-
-static int apply_ram_timings(volatile unsigned short *memregs, void *data)
-{
- int *ram_timings = data;
- int i, val;
-
- for (i = 0; i < 7; i++)
- {
- ram_timings[i] += ram_ranges[i].adj;
- if (ram_timings[i] < ram_ranges[i].min || ram_timings[i] > ram_ranges[i].max) {
- fprintf(stderr, "pollux_set: invalid RAM timing %d\n", i);
- return -1;
- }
- }
-
- val = memregs[0x14802>>1] & 0x0f00;
- val |= (ram_timings[4] << 12) | (ram_timings[5] << 4) | ram_timings[6];
- memregs[0x14802>>1] = val;
-
- val = memregs[0x14804>>1] & 0x4000;
- val |= (ram_timings[0] << 12) | (ram_timings[1] << 8) |
- (ram_timings[2] << 4) | ram_timings[3];
- val |= 0x8000;
- memregs[0x14804>>1] = val;
-
- for (i = 0; i < 0x100000 && (memregs[0x14804>>1] & 0x8000); i++)
- ;
-
- return 0;
-}
-
-static int apply_dpc_clkdiv0(volatile unsigned short *memregs, void *data)
-{
- int pcd = *(int *)data;
- int tmp;
-
- if ((pcd - 1) & ~0x3f) {
- fprintf(stderr, "pollux_set: invalid lcd clkdiv0: %d\n", pcd);
- return -1;
- }
-
- pcd = (pcd - 1) & 0x3f;
- tmp = memregs[0x31c4>>1];
- memregs[0x31c4>>1] = (tmp & ~0x3f0) | (pcd << 4);
-
- return 0;
-}
-
-static int apply_cpuclk(volatile unsigned short *memregs, void *data)
-{
- volatile unsigned int *memregl = (volatile void *)memregs;
- int mhz = *(int *)data;
- int adiv, mdiv, pdiv, sdiv = 0;
- int i, vf000, vf004;
-
- // m = MDIV, p = PDIV, s = SDIV
- #define SYS_CLK_FREQ 27
- pdiv = 9;
- mdiv = (mhz * pdiv) / SYS_CLK_FREQ;
- if (mdiv & ~0x3ff)
- return -1;
- vf004 = (pdiv<<18) | (mdiv<<8) | sdiv;
-
- // attempt to keep AHB the divider close to 250, but not higher
- for (adiv = 1; mhz / adiv > 250; adiv++)
- ;
-
- vf000 = memregl[0xf000>>2];
- vf000 = (vf000 & ~0x3c0) | ((adiv - 1) << 6);
- memregl[0xf000>>2] = vf000;
- memregl[0xf004>>2] = vf004;
- memregl[0xf07c>>2] |= 0x8000;
- for (i = 0; (memregl[0xf07c>>2] & 0x8000) && i < 0x100000; i++)
- ;
-
- printf("clock set to %dMHz, AHB set to %dMHz\n", mhz, mhz / adiv);
- return 0;
-}
-
-static int lcd_timings[8];
-static int ram_timings[7];
-static int dpc_clkdiv0;
-static int cpuclk;
-
-static const char lcd_t_help[] = "htotal,hswidth,hastart,haend,vtotal,vswidth,vastart,vaend";
-static const char ram_t_help[] = "CAS,tRC,tRAS,tWR,tMRD,tRP,tRCD";
-
-static const struct {
- const char *name;
- const char *help;
- int (*parse)(const char *str, void *data);
- int (*apply)(volatile unsigned short *memregs, void *data);
- void *data;
-}
-all_params[] = {
- { "lcd_timings", lcd_t_help, parse_lcd_timings, apply_lcd_timings, lcd_timings },
- { "ram_timings", ram_t_help, parse_ram_timings, apply_ram_timings, ram_timings },
- { "dpc_clkdiv0", "divider", parse_decimal, apply_dpc_clkdiv0, &dpc_clkdiv0 },
- { "clkdiv0", "divider", parse_decimal, apply_dpc_clkdiv0, &dpc_clkdiv0 }, /* alias */
- { "cpuclk", "MHZ", parse_decimal, apply_cpuclk, &cpuclk },
-};
-#define ALL_PARAM_COUNT (sizeof(all_params) / sizeof(all_params[0]))
-
-/*
- * set timings based on preformated string
- * returns 0 on success.
- */
-int pollux_set(volatile unsigned short *memregs, const char *str)
-{
- int parsed_params[ALL_PARAM_COUNT];
- int applied_params[ALL_PARAM_COUNT];
- int applied_something = 0;
- const char *p, *po;
- int i, ret;
-
- if (str == NULL)
- return -1;
-
- memset(parsed_params, 0, sizeof(parsed_params));
- memset(applied_params, 0, sizeof(applied_params));
-
- p = str;
- while (1)
- {
-again:
- while (*p == ';' || *p == ' ')
- p++;
- if (*p == 0)
- break;
-
- for (i = 0; i < ALL_PARAM_COUNT; i++)
- {
- int param_len = strlen(all_params[i].name);
- if (strncmp(p, all_params[i].name, param_len) == 0 && p[param_len] == '=')
- {
- p += param_len + 1;
- ret = all_params[i].parse(p, all_params[i].data);
- if (ret < 0) {
- fprintf(stderr, "pollux_set parser: error at %-10s\n", p);
- fprintf(stderr, " valid format is: <%s>\n", all_params[i].help);
- return -1;
- }
- parsed_params[i] = 1;
- p += ret;
- goto again;
- }
- }
-
- /* Unknown param. Attempt to be forward compatible and ignore it. */
- for (po = p; *p != 0 && *p != ';'; p++)
- ;
-
- fprintf(stderr, "unhandled param: ");
- fwrite(po, 1, p - po, stderr);
- fprintf(stderr, "\n");
- }
-
- /* validate and apply */
- for (i = 0; i < ALL_PARAM_COUNT; i++)
- {
- if (!parsed_params[i])
- continue;
-
- ret = all_params[i].apply(memregs, all_params[i].data);
- if (ret < 0) {
- fprintf(stderr, "pollux_set: failed to apply %s (bad value?)\n",
- all_params[i].name);
- continue;
- }
-
- applied_something = 1;
- applied_params[i] = 1;
- }
-
- if (applied_something)
- {
- int c;
- printf("applied: ");
- for (i = c = 0; i < ALL_PARAM_COUNT; i++)
- {
- if (!applied_params[i])
- continue;
- if (c != 0)
- printf(", ");
- printf("%s", all_params[i].name);
- c++;
- }
- printf("\n");
- }
-
- return 0;
-}
-
-#ifdef BINARY
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <sys/mman.h>
-#include <unistd.h>
-
-static void usage(const char *binary)
-{
- int i;
- printf("usage:\n%s <set_str[;set_str[;...]]>\n"
- "set_str:\n", binary);
- for (i = 0; i < ALL_PARAM_COUNT; i++)
- printf(" %s=<%s>\n", all_params[i].name, all_params[i].help);
-}
-
-int main(int argc, char *argv[])
-{
- volatile unsigned short *memregs;
- int ret, memdev;
-
- if (argc != 2) {
- usage(argv[0]);
- return 1;
- }
-
- memdev = open("/dev/mem", O_RDWR);
- if (memdev == -1)
- {
- perror("open(/dev/mem) failed");
- return 1;
- }
-
- memregs = mmap(0, 0x20000, PROT_READ|PROT_WRITE, MAP_SHARED, memdev, 0xc0000000);
- if (memregs == MAP_FAILED)
- {
- perror("mmap(memregs) failed");
- close(memdev);
- return 1;
- }
-
- ret = pollux_set(memregs, argv[1]);
-
- munmap((void *)memregs, 0x20000);
- close(memdev);
-
- return ret;
-}
-#endif
diff --git a/frontend/320240/skin/background.png b/frontend/320240/skin/background.png
deleted file mode 100644
index 0efdd18..0000000
--- a/frontend/320240/skin/background.png
+++ /dev/null
Binary files differ
diff --git a/frontend/320240/skin/font.png b/frontend/320240/skin/font.png
deleted file mode 100644
index c526a08..0000000
--- a/frontend/320240/skin/font.png
+++ /dev/null
Binary files differ
diff --git a/frontend/320240/skin/readme.txt b/frontend/320240/skin/readme.txt
deleted file mode 100644
index dd83963..0000000
--- a/frontend/320240/skin/readme.txt
+++ /dev/null
@@ -1,8 +0,0 @@
-The skin images can be customized, but there are several limitations:
-
-background.png - must be 320x240 image with 24bit RGB colors.
-font.png - must be 128x160 8bit grayscale image.
-selector.png - must be 8x10 8bit grayscale image.
-
-Font and selector colors can be changed by editing skin.txt.
-
diff --git a/frontend/320240/skin/selector.png b/frontend/320240/skin/selector.png
deleted file mode 100644
index 5062cc2..0000000
--- a/frontend/320240/skin/selector.png
+++ /dev/null
Binary files differ
diff --git a/frontend/320240/skin/skin.txt b/frontend/320240/skin/skin.txt
deleted file mode 100644
index 1d6979f..0000000
--- a/frontend/320240/skin/skin.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-// html-style hex color codes, ex. ff0000 is red, 0000ff is blue, etc.
-text_color=ffffc0
-selection_color=808010
-
diff --git a/frontend/320240/ui_gp2x.h b/frontend/320240/ui_gp2x.h
deleted file mode 100644
index a9c4413..0000000
--- a/frontend/320240/ui_gp2x.h
+++ /dev/null
@@ -1,15 +0,0 @@
-#ifndef UI_FEATURES_H
-#define UI_FEATURES_H
-
-#define MENU_BIOS_PATH "pcsx_rearmed/bios/"
-#define MENU_SHOW_VARSCALER 0
-#define MENU_SHOW_VOUTMODE 0
-#define MENU_SHOW_SCALER2 1
-#define MENU_SHOW_NUBS_BTNS 0
-#define MENU_SHOW_VIBRATION 1
-#define MENU_SHOW_DEADZONE 1
-#define MENU_SHOW_MINIMIZE 0
-#define MENU_SHOW_FULLSCREEN 0
-#define MENU_SHOW_VOLUME 1
-
-#endif // UI_FEATURES_H
diff --git a/frontend/3ds/3ds_utils.h b/frontend/3ds/3ds_utils.h
new file mode 100644
index 0000000..3d50a66
--- /dev/null
+++ b/frontend/3ds/3ds_utils.h
@@ -0,0 +1,66 @@
+#ifndef _3DS_UTILS_H
+#define _3DS_UTILS_H
+
+#include <stdio.h>
+
+#define MEMOP_PROT 6
+#define MEMOP_MAP 4
+#define MEMOP_UNMAP 5
+
+void* linearMemAlign(size_t size, size_t alignment);
+void linearFree(void* mem);
+
+int32_t svcDuplicateHandle(uint32_t* out, uint32_t original);
+int32_t svcCloseHandle(uint32_t handle);
+int32_t svcControlMemory(void* addr_out, void* addr0, void* addr1, uint32_t size, uint32_t op, uint32_t perm);
+int32_t svcControlProcessMemory(uint32_t process, void* addr0, void* addr1, uint32_t size, uint32_t op, uint32_t perm);
+
+int32_t svcCreateThread(int32_t* thread, void *(*entrypoint)(void*), void* arg, void* stack_top, int32_t thread_priority, int32_t processor_id);
+int32_t svcWaitSynchronization(int32_t handle, int64_t nanoseconds);
+void svcExitThread(void) __attribute__((noreturn));
+
+int32_t svcBackdoor(int32_t (*callback)(void));
+
+#define DEBUG_HOLD() do{printf("%s@%s:%d.\n",__FUNCTION__, __FILE__, __LINE__);fflush(stdout);wait_for_input();}while(0)
+
+void wait_for_input(void);
+
+extern __attribute__((weak)) int __ctr_svchax;
+
+typedef int32_t (*ctr_callback_type)(void);
+
+static inline void ctr_invalidate_ICache_kernel(void)
+{
+ __asm__ volatile(
+ "cpsid aif\n\t"
+ "mov r0, #0\n\t"
+ "mcr p15, 0, r0, c7, c5, 0\n\t");
+}
+
+static inline void ctr_flush_DCache_kernel(void)
+{
+ __asm__ volatile(
+ "cpsid aif\n\t"
+ "mov r0, #0\n\t"
+ "mcr p15, 0, r0, c7, c10, 0\n\t");
+}
+
+static inline void ctr_invalidate_ICache(void)
+{
+ svcBackdoor((ctr_callback_type)ctr_invalidate_ICache_kernel);
+}
+
+static inline void ctr_flush_DCache(void)
+{
+ svcBackdoor((ctr_callback_type)ctr_flush_DCache_kernel);
+}
+
+
+static inline void ctr_flush_invalidate_cache(void)
+{
+ ctr_flush_DCache();
+ ctr_invalidate_ICache();
+}
+
+
+#endif // _3DS_UTILS_H
diff --git a/frontend/3ds/pthread.h b/frontend/3ds/pthread.h
new file mode 100644
index 0000000..2c2bf6b
--- /dev/null
+++ b/frontend/3ds/pthread.h
@@ -0,0 +1,56 @@
+
+#ifndef _3DS_PTHREAD_WRAP__
+#define _3DS_PTHREAD_WRAP__
+
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+
+#include "3ds_utils.h"
+
+#define CTR_PTHREAD_STACK_SIZE 0x10000
+
+typedef struct
+{
+ int32_t handle;
+ uint32_t* stack;
+}pthread_t;
+typedef int pthread_attr_t;
+
+static inline int pthread_create(pthread_t *thread,
+ const pthread_attr_t *attr, void *(*start_routine)(void*), void *arg)
+{
+
+ thread->stack = linearMemAlign(CTR_PTHREAD_STACK_SIZE, 8);
+
+ svcCreateThread(&thread->handle, start_routine, arg,
+ (uint32_t*)((uint32_t)thread->stack + CTR_PTHREAD_STACK_SIZE),
+ 0x25, 1);
+
+ return 1;
+}
+
+
+static inline int pthread_join(pthread_t thread, void **retval)
+{
+ (void)retval;
+
+ if(svcWaitSynchronization(thread.handle, INT64_MAX))
+ return -1;
+
+ linearFree(thread.stack);
+
+ return 0;
+}
+
+
+static inline void pthread_exit(void *retval)
+{
+ (void)retval;
+
+ svcExitThread();
+}
+
+
+#endif //_3DS_PTHREAD_WRAP__
+
diff --git a/frontend/3ds/sys/mman.h b/frontend/3ds/sys/mman.h
new file mode 100644
index 0000000..61dde6c
--- /dev/null
+++ b/frontend/3ds/sys/mman.h
@@ -0,0 +1,107 @@
+#ifndef MMAN_H
+#define MMAN_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <malloc.h>
+
+#include "3ds_utils.h"
+
+#define PROT_READ 0b001
+#define PROT_WRITE 0b010
+#define PROT_EXEC 0b100
+#define MAP_PRIVATE 2
+#define MAP_FIXED 0x10
+#define MAP_ANONYMOUS 0x20
+
+#define MAP_FAILED ((void *)-1)
+
+static void* dynarec_cache = NULL;
+static void* dynarec_cache_mapping = NULL;
+
+static inline void* mmap(void *addr, size_t len, int prot, int flags, int fd, off_t offset)
+{
+ (void)fd;
+ (void)offset;
+
+ void* addr_out;
+
+ if((prot == (PROT_READ | PROT_WRITE | PROT_EXEC)) &&
+ (flags == (MAP_PRIVATE | MAP_ANONYMOUS)))
+ {
+ if(__ctr_svchax)
+ {
+ /* this hack works only for pcsx_rearmed */
+ uint32_t currentHandle;
+
+ if(!dynarec_cache)
+ dynarec_cache = memalign(0x1000, len);
+
+ svcDuplicateHandle(&currentHandle, 0xFFFF8001);
+ svcControlProcessMemory(currentHandle, addr, dynarec_cache,
+ len, MEMOP_MAP, prot);
+ svcCloseHandle(currentHandle);
+ dynarec_cache_mapping = addr;
+ return addr;
+ }
+ else
+ {
+ printf("tried to mmap RWX pages without svcControlProcessMemory access !\n");
+ return MAP_FAILED;
+ }
+
+ }
+
+ addr_out = malloc(len);
+ if(!addr_out)
+ return MAP_FAILED;
+
+ return addr_out;
+}
+
+static inline int mprotect(void *addr, size_t len, int prot)
+{
+ if(__ctr_svchax)
+ {
+ uint32_t currentHandle;
+ svcDuplicateHandle(&currentHandle, 0xFFFF8001);
+ svcControlProcessMemory(currentHandle, addr, NULL,
+ len, MEMOP_PROT, prot);
+ svcCloseHandle(currentHandle);
+ return 0;
+ }
+
+ printf("mprotect called without svcControlProcessMemory access !\n");
+ return -1;
+}
+
+static inline int munmap(void *addr, size_t len)
+{
+ if((addr == dynarec_cache_mapping) && __ctr_svchax)
+ {
+ uint32_t currentHandle;
+ svcDuplicateHandle(&currentHandle, 0xFFFF8001);
+ svcControlProcessMemory(currentHandle,
+ dynarec_cache, dynarec_cache_mapping,
+ len, MEMOP_UNMAP, 0b111);
+ svcCloseHandle(currentHandle);
+ dynarec_cache_mapping = NULL;
+
+ }
+ else
+ free(addr);
+
+ return 0;
+}
+
+#ifdef __cplusplus
+};
+#endif
+
+#endif // MMAN_H
+
diff --git a/frontend/3ds/zconf.h b/frontend/3ds/zconf.h
new file mode 100644
index 0000000..996fff2
--- /dev/null
+++ b/frontend/3ds/zconf.h
@@ -0,0 +1,511 @@
+/* zconf.h -- configuration of the zlib compression library
+ * Copyright (C) 1995-2013 Jean-loup Gailly.
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* @(#) $Id$ */
+
+#ifndef ZCONF_H
+#define ZCONF_H
+
+/*
+ * If you *really* need a unique prefix for all types and library functions,
+ * compile with -DZ_PREFIX. The "standard" zlib should be compiled without it.
+ * Even better than compiling with -DZ_PREFIX would be to use configure to set
+ * this permanently in zconf.h using "./configure --zprefix".
+ */
+#ifdef Z_PREFIX /* may be set to #if 1 by ./configure */
+# define Z_PREFIX_SET
+
+/* all linked symbols */
+# define _dist_code z__dist_code
+# define _length_code z__length_code
+# define _tr_align z__tr_align
+# define _tr_flush_bits z__tr_flush_bits
+# define _tr_flush_block z__tr_flush_block
+# define _tr_init z__tr_init
+# define _tr_stored_block z__tr_stored_block
+# define _tr_tally z__tr_tally
+# define adler32 z_adler32
+# define adler32_combine z_adler32_combine
+# define adler32_combine64 z_adler32_combine64
+# ifndef Z_SOLO
+# define compress z_compress
+# define compress2 z_compress2
+# define compressBound z_compressBound
+# endif
+# define crc32 z_crc32
+# define crc32_combine z_crc32_combine
+# define crc32_combine64 z_crc32_combine64
+# define deflate z_deflate
+# define deflateBound z_deflateBound
+# define deflateCopy z_deflateCopy
+# define deflateEnd z_deflateEnd
+# define deflateInit2_ z_deflateInit2_
+# define deflateInit_ z_deflateInit_
+# define deflateParams z_deflateParams
+# define deflatePending z_deflatePending
+# define deflatePrime z_deflatePrime
+# define deflateReset z_deflateReset
+# define deflateResetKeep z_deflateResetKeep
+# define deflateSetDictionary z_deflateSetDictionary
+# define deflateSetHeader z_deflateSetHeader
+# define deflateTune z_deflateTune
+# define deflate_copyright z_deflate_copyright
+# define get_crc_table z_get_crc_table
+# ifndef Z_SOLO
+# define gz_error z_gz_error
+# define gz_intmax z_gz_intmax
+# define gz_strwinerror z_gz_strwinerror
+# define gzbuffer z_gzbuffer
+# define gzclearerr z_gzclearerr
+# define gzclose z_gzclose
+# define gzclose_r z_gzclose_r
+# define gzclose_w z_gzclose_w
+# define gzdirect z_gzdirect
+# define gzdopen z_gzdopen
+# define gzeof z_gzeof
+# define gzerror z_gzerror
+# define gzflush z_gzflush
+# define gzgetc z_gzgetc
+# define gzgetc_ z_gzgetc_
+# define gzgets z_gzgets
+# define gzoffset z_gzoffset
+# define gzoffset64 z_gzoffset64
+# define gzopen z_gzopen
+# define gzopen64 z_gzopen64
+# ifdef _WIN32
+# define gzopen_w z_gzopen_w
+# endif
+# define gzprintf z_gzprintf
+# define gzvprintf z_gzvprintf
+# define gzputc z_gzputc
+# define gzputs z_gzputs
+# define gzread z_gzread
+# define gzrewind z_gzrewind
+# define gzseek z_gzseek
+# define gzseek64 z_gzseek64
+# define gzsetparams z_gzsetparams
+# define gztell z_gztell
+# define gztell64 z_gztell64
+# define gzungetc z_gzungetc
+# define gzwrite z_gzwrite
+# endif
+# define inflate z_inflate
+# define inflateBack z_inflateBack
+# define inflateBackEnd z_inflateBackEnd
+# define inflateBackInit_ z_inflateBackInit_
+# define inflateCopy z_inflateCopy
+# define inflateEnd z_inflateEnd
+# define inflateGetHeader z_inflateGetHeader
+# define inflateInit2_ z_inflateInit2_
+# define inflateInit_ z_inflateInit_
+# define inflateMark z_inflateMark
+# define inflatePrime z_inflatePrime
+# define inflateReset z_inflateReset
+# define inflateReset2 z_inflateReset2
+# define inflateSetDictionary z_inflateSetDictionary
+# define inflateGetDictionary z_inflateGetDictionary
+# define inflateSync z_inflateSync
+# define inflateSyncPoint z_inflateSyncPoint
+# define inflateUndermine z_inflateUndermine
+# define inflateResetKeep z_inflateResetKeep
+# define inflate_copyright z_inflate_copyright
+# define inflate_fast z_inflate_fast
+# define inflate_table z_inflate_table
+# ifndef Z_SOLO
+# define uncompress z_uncompress
+# endif
+# define zError z_zError
+# ifndef Z_SOLO
+# define zcalloc z_zcalloc
+# define zcfree z_zcfree
+# endif
+# define zlibCompileFlags z_zlibCompileFlags
+# define zlibVersion z_zlibVersion
+
+/* all zlib typedefs in zlib.h and zconf.h */
+# define Byte z_Byte
+# define Bytef z_Bytef
+# define alloc_func z_alloc_func
+# define charf z_charf
+# define free_func z_free_func
+# ifndef Z_SOLO
+# define gzFile z_gzFile
+# endif
+# define gz_header z_gz_header
+# define gz_headerp z_gz_headerp
+# define in_func z_in_func
+# define intf z_intf
+# define out_func z_out_func
+# define uInt z_uInt
+# define uIntf z_uIntf
+# define uLong z_uLong
+# define uLongf z_uLongf
+# define voidp z_voidp
+# define voidpc z_voidpc
+# define voidpf z_voidpf
+
+/* all zlib structs in zlib.h and zconf.h */
+# define gz_header_s z_gz_header_s
+# define internal_state z_internal_state
+
+#endif
+
+#if defined(__MSDOS__) && !defined(MSDOS)
+# define MSDOS
+#endif
+#if (defined(OS_2) || defined(__OS2__)) && !defined(OS2)
+# define OS2
+#endif
+#if defined(_WINDOWS) && !defined(WINDOWS)
+# define WINDOWS
+#endif
+#if defined(_WIN32) || defined(_WIN32_WCE) || defined(__WIN32__)
+# ifndef WIN32
+# define WIN32
+# endif
+#endif
+#if (defined(MSDOS) || defined(OS2) || defined(WINDOWS)) && !defined(WIN32)
+# if !defined(__GNUC__) && !defined(__FLAT__) && !defined(__386__)
+# ifndef SYS16BIT
+# define SYS16BIT
+# endif
+# endif
+#endif
+
+/*
+ * Compile with -DMAXSEG_64K if the alloc function cannot allocate more
+ * than 64k bytes at a time (needed on systems with 16-bit int).
+ */
+#ifdef SYS16BIT
+# define MAXSEG_64K
+#endif
+#ifdef MSDOS
+# define UNALIGNED_OK
+#endif
+
+#ifdef __STDC_VERSION__
+# ifndef STDC
+# define STDC
+# endif
+# if __STDC_VERSION__ >= 199901L
+# ifndef STDC99
+# define STDC99
+# endif
+# endif
+#endif
+#if !defined(STDC) && (defined(__STDC__) || defined(__cplusplus))
+# define STDC
+#endif
+#if !defined(STDC) && (defined(__GNUC__) || defined(__BORLANDC__))
+# define STDC
+#endif
+#if !defined(STDC) && (defined(MSDOS) || defined(WINDOWS) || defined(WIN32))
+# define STDC
+#endif
+#if !defined(STDC) && (defined(OS2) || defined(__HOS_AIX__))
+# define STDC
+#endif
+
+#if defined(__OS400__) && !defined(STDC) /* iSeries (formerly AS/400). */
+# define STDC
+#endif
+
+#ifndef STDC
+# ifndef const /* cannot use !defined(STDC) && !defined(const) on Mac */
+# define const /* note: need a more gentle solution here */
+# endif
+#endif
+
+#if defined(ZLIB_CONST) && !defined(z_const)
+# define z_const const
+#else
+# define z_const
+#endif
+
+/* Some Mac compilers merge all .h files incorrectly: */
+#if defined(__MWERKS__)||defined(applec)||defined(THINK_C)||defined(__SC__)
+# define NO_DUMMY_DECL
+#endif
+
+/* Maximum value for memLevel in deflateInit2 */
+#ifndef MAX_MEM_LEVEL
+# ifdef MAXSEG_64K
+# define MAX_MEM_LEVEL 8
+# else
+# define MAX_MEM_LEVEL 9
+# endif
+#endif
+
+/* Maximum value for windowBits in deflateInit2 and inflateInit2.
+ * WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files
+ * created by gzip. (Files created by minigzip can still be extracted by
+ * gzip.)
+ */
+#ifndef MAX_WBITS
+# define MAX_WBITS 15 /* 32K LZ77 window */
+#endif
+
+/* The memory requirements for deflate are (in bytes):
+ (1 << (windowBits+2)) + (1 << (memLevel+9))
+ that is: 128K for windowBits=15 + 128K for memLevel = 8 (default values)
+ plus a few kilobytes for small objects. For example, if you want to reduce
+ the default memory requirements from 256K to 128K, compile with
+ make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7"
+ Of course this will generally degrade compression (there's no free lunch).
+
+ The memory requirements for inflate are (in bytes) 1 << windowBits
+ that is, 32K for windowBits=15 (default value) plus a few kilobytes
+ for small objects.
+*/
+
+ /* Type declarations */
+
+#ifndef OF /* function prototypes */
+# ifdef STDC
+# define OF(args) args
+# else
+# define OF(args) ()
+# endif
+#endif
+
+#ifndef Z_ARG /* function prototypes for stdarg */
+# if defined(STDC) || defined(Z_HAVE_STDARG_H)
+# define Z_ARG(args) args
+# else
+# define Z_ARG(args) ()
+# endif
+#endif
+
+/* The following definitions for FAR are needed only for MSDOS mixed
+ * model programming (small or medium model with some far allocations).
+ * This was tested only with MSC; for other MSDOS compilers you may have
+ * to define NO_MEMCPY in zutil.h. If you don't need the mixed model,
+ * just define FAR to be empty.
+ */
+#ifdef SYS16BIT
+# if defined(M_I86SM) || defined(M_I86MM)
+ /* MSC small or medium model */
+# define SMALL_MEDIUM
+# ifdef _MSC_VER
+# define FAR _far
+# else
+# define FAR far
+# endif
+# endif
+# if (defined(__SMALL__) || defined(__MEDIUM__))
+ /* Turbo C small or medium model */
+# define SMALL_MEDIUM
+# ifdef __BORLANDC__
+# define FAR _far
+# else
+# define FAR far
+# endif
+# endif
+#endif
+
+#if defined(WINDOWS) || defined(WIN32)
+ /* If building or using zlib as a DLL, define ZLIB_DLL.
+ * This is not mandatory, but it offers a little performance increase.
+ */
+# ifdef ZLIB_DLL
+# if defined(WIN32) && (!defined(__BORLANDC__) || (__BORLANDC__ >= 0x500))
+# ifdef ZLIB_INTERNAL
+# define ZEXTERN extern __declspec(dllexport)
+# else
+# define ZEXTERN extern __declspec(dllimport)
+# endif
+# endif
+# endif /* ZLIB_DLL */
+ /* If building or using zlib with the WINAPI/WINAPIV calling convention,
+ * define ZLIB_WINAPI.
+ * Caution: the standard ZLIB1.DLL is NOT compiled using ZLIB_WINAPI.
+ */
+# ifdef ZLIB_WINAPI
+# ifdef FAR
+# undef FAR
+# endif
+# include <windows.h>
+ /* No need for _export, use ZLIB.DEF instead. */
+ /* For complete Windows compatibility, use WINAPI, not __stdcall. */
+# define ZEXPORT WINAPI
+# ifdef WIN32
+# define ZEXPORTVA WINAPIV
+# else
+# define ZEXPORTVA FAR CDECL
+# endif
+# endif
+#endif
+
+#if defined (__BEOS__)
+# ifdef ZLIB_DLL
+# ifdef ZLIB_INTERNAL
+# define ZEXPORT __declspec(dllexport)
+# define ZEXPORTVA __declspec(dllexport)
+# else
+# define ZEXPORT __declspec(dllimport)
+# define ZEXPORTVA __declspec(dllimport)
+# endif
+# endif
+#endif
+
+#ifndef ZEXTERN
+# define ZEXTERN extern
+#endif
+#ifndef ZEXPORT
+# define ZEXPORT
+#endif
+#ifndef ZEXPORTVA
+# define ZEXPORTVA
+#endif
+
+#ifndef FAR
+# define FAR
+#endif
+
+#if !defined(__MACTYPES__)
+typedef unsigned char Byte; /* 8 bits */
+#endif
+typedef unsigned int uInt; /* 16 bits or more */
+typedef unsigned long uLong; /* 32 bits or more */
+
+#ifdef SMALL_MEDIUM
+ /* Borland C/C++ and some old MSC versions ignore FAR inside typedef */
+# define Bytef Byte FAR
+#else
+ typedef Byte FAR Bytef;
+#endif
+typedef char FAR charf;
+typedef int FAR intf;
+typedef uInt FAR uIntf;
+typedef uLong FAR uLongf;
+
+#ifdef STDC
+ typedef void const *voidpc;
+ typedef void FAR *voidpf;
+ typedef void *voidp;
+#else
+ typedef Byte const *voidpc;
+ typedef Byte FAR *voidpf;
+ typedef Byte *voidp;
+#endif
+
+#if !defined(Z_U4) && !defined(Z_SOLO) && defined(STDC)
+# include <limits.h>
+# if (UINT_MAX == 0xffffffffUL)
+# define Z_U4 unsigned
+# elif (ULONG_MAX == 0xffffffffUL)
+# define Z_U4 unsigned long
+# elif (USHRT_MAX == 0xffffffffUL)
+# define Z_U4 unsigned short
+# endif
+#endif
+
+#ifdef Z_U4
+ typedef Z_U4 z_crc_t;
+#else
+ typedef unsigned long z_crc_t;
+#endif
+
+#if 1 /* was set to #if 1 by ./configure */
+# define Z_HAVE_UNISTD_H
+#endif
+
+#if 1 /* was set to #if 1 by ./configure */
+# define Z_HAVE_STDARG_H
+#endif
+
+#ifdef STDC
+# ifndef Z_SOLO
+# include <sys/types.h> /* for off_t */
+# endif
+#endif
+
+#if defined(STDC) || defined(Z_HAVE_STDARG_H)
+# ifndef Z_SOLO
+# include <stdarg.h> /* for va_list */
+# endif
+#endif
+
+#ifdef _WIN32
+# ifndef Z_SOLO
+# include <stddef.h> /* for wchar_t */
+# endif
+#endif
+
+/* a little trick to accommodate both "#define _LARGEFILE64_SOURCE" and
+ * "#define _LARGEFILE64_SOURCE 1" as requesting 64-bit operations, (even
+ * though the former does not conform to the LFS document), but considering
+ * both "#undef _LARGEFILE64_SOURCE" and "#define _LARGEFILE64_SOURCE 0" as
+ * equivalently requesting no 64-bit operations
+ */
+#if defined(_LARGEFILE64_SOURCE) && -_LARGEFILE64_SOURCE - -1 == 1
+# undef _LARGEFILE64_SOURCE
+#endif
+
+#if defined(__WATCOMC__) && !defined(Z_HAVE_UNISTD_H)
+# define Z_HAVE_UNISTD_H
+#endif
+#ifndef Z_SOLO
+# if defined(Z_HAVE_UNISTD_H) || defined(_LARGEFILE64_SOURCE)
+# include <unistd.h> /* for SEEK_*, off_t, and _LFS64_LARGEFILE */
+# ifdef VMS
+# include <unixio.h> /* for off_t */
+# endif
+# ifndef z_off_t
+# define z_off_t off_t
+# endif
+# endif
+#endif
+
+#if defined(_LFS64_LARGEFILE) && _LFS64_LARGEFILE-0
+# define Z_LFS64
+#endif
+
+#if defined(_LARGEFILE64_SOURCE) && defined(Z_LFS64)
+# define Z_LARGE64
+#endif
+
+#if defined(_FILE_OFFSET_BITS) && _FILE_OFFSET_BITS-0 == 64 && defined(Z_LFS64)
+# define Z_WANT64
+#endif
+
+#if !defined(SEEK_SET) && !defined(Z_SOLO)
+# define SEEK_SET 0 /* Seek from beginning of file. */
+# define SEEK_CUR 1 /* Seek from current position. */
+# define SEEK_END 2 /* Set file pointer to EOF plus "offset" */
+#endif
+
+#ifndef z_off_t
+# define z_off_t long
+#endif
+
+#if !defined(_WIN32) && defined(Z_LARGE64)
+# define z_off64_t off64_t
+#else
+# if defined(_WIN32) && !defined(__GNUC__) && !defined(Z_SOLO)
+# define z_off64_t __int64
+# else
+# define z_off64_t z_off_t
+# endif
+#endif
+
+/* MVS linker does not support external names larger than 8 bytes */
+#if defined(__MVS__)
+ #pragma map(deflateInit_,"DEIN")
+ #pragma map(deflateInit2_,"DEIN2")
+ #pragma map(deflateEnd,"DEEND")
+ #pragma map(deflateBound,"DEBND")
+ #pragma map(inflateInit_,"ININ")
+ #pragma map(inflateInit2_,"ININ2")
+ #pragma map(inflateEnd,"INEND")
+ #pragma map(inflateSync,"INSY")
+ #pragma map(inflateSetDictionary,"INSEDI")
+ #pragma map(compressBound,"CMBND")
+ #pragma map(inflate_table,"INTABL")
+ #pragma map(inflate_fast,"INFA")
+ #pragma map(inflate_copyright,"INCOPY")
+#endif
+
+#endif /* ZCONF_H */
diff --git a/frontend/3ds/zlib.h b/frontend/3ds/zlib.h
new file mode 100644
index 0000000..3e0c767
--- /dev/null
+++ b/frontend/3ds/zlib.h
@@ -0,0 +1,1768 @@
+/* zlib.h -- interface of the 'zlib' general purpose compression library
+ version 1.2.8, April 28th, 2013
+
+ Copyright (C) 1995-2013 Jean-loup Gailly and Mark Adler
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+
+ Jean-loup Gailly Mark Adler
+ jloup@gzip.org madler@alumni.caltech.edu
+
+
+ The data format used by the zlib library is described by RFCs (Request for
+ Comments) 1950 to 1952 in the files http://tools.ietf.org/html/rfc1950
+ (zlib format), rfc1951 (deflate format) and rfc1952 (gzip format).
+*/
+
+#ifndef ZLIB_H
+#define ZLIB_H
+
+#include "zconf.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define ZLIB_VERSION "1.2.8"
+#define ZLIB_VERNUM 0x1280
+#define ZLIB_VER_MAJOR 1
+#define ZLIB_VER_MINOR 2
+#define ZLIB_VER_REVISION 8
+#define ZLIB_VER_SUBREVISION 0
+
+/*
+ The 'zlib' compression library provides in-memory compression and
+ decompression functions, including integrity checks of the uncompressed data.
+ This version of the library supports only one compression method (deflation)
+ but other algorithms will be added later and will have the same stream
+ interface.
+
+ Compression can be done in a single step if the buffers are large enough,
+ or can be done by repeated calls of the compression function. In the latter
+ case, the application must provide more input and/or consume the output
+ (providing more output space) before each call.
+
+ The compressed data format used by default by the in-memory functions is
+ the zlib format, which is a zlib wrapper documented in RFC 1950, wrapped
+ around a deflate stream, which is itself documented in RFC 1951.
+
+ The library also supports reading and writing files in gzip (.gz) format
+ with an interface similar to that of stdio using the functions that start
+ with "gz". The gzip format is different from the zlib format. gzip is a
+ gzip wrapper, documented in RFC 1952, wrapped around a deflate stream.
+
+ This library can optionally read and write gzip streams in memory as well.
+
+ The zlib format was designed to be compact and fast for use in memory
+ and on communications channels. The gzip format was designed for single-
+ file compression on file systems, has a larger header than zlib to maintain
+ directory information, and uses a different, slower check method than zlib.
+
+ The library does not install any signal handler. The decoder checks
+ the consistency of the compressed data, so the library should never crash
+ even in case of corrupted input.
+*/
+
+typedef voidpf (*alloc_func) OF((voidpf opaque, uInt items, uInt size));
+typedef void (*free_func) OF((voidpf opaque, voidpf address));
+
+struct internal_state;
+
+typedef struct z_stream_s {
+ z_const Bytef *next_in; /* next input byte */
+ uInt avail_in; /* number of bytes available at next_in */
+ uLong total_in; /* total number of input bytes read so far */
+
+ Bytef *next_out; /* next output byte should be put there */
+ uInt avail_out; /* remaining free space at next_out */
+ uLong total_out; /* total number of bytes output so far */
+
+ z_const char *msg; /* last error message, NULL if no error */
+ struct internal_state FAR *state; /* not visible by applications */
+
+ alloc_func zalloc; /* used to allocate the internal state */
+ free_func zfree; /* used to free the internal state */
+ voidpf opaque; /* private data object passed to zalloc and zfree */
+
+ int data_type; /* best guess about the data type: binary or text */
+ uLong adler; /* adler32 value of the uncompressed data */
+ uLong reserved; /* reserved for future use */
+} z_stream;
+
+typedef z_stream FAR *z_streamp;
+
+/*
+ gzip header information passed to and from zlib routines. See RFC 1952
+ for more details on the meanings of these fields.
+*/
+typedef struct gz_header_s {
+ int text; /* true if compressed data believed to be text */
+ uLong time; /* modification time */
+ int xflags; /* extra flags (not used when writing a gzip file) */
+ int os; /* operating system */
+ Bytef *extra; /* pointer to extra field or Z_NULL if none */
+ uInt extra_len; /* extra field length (valid if extra != Z_NULL) */
+ uInt extra_max; /* space at extra (only when reading header) */
+ Bytef *name; /* pointer to zero-terminated file name or Z_NULL */
+ uInt name_max; /* space at name (only when reading header) */
+ Bytef *comment; /* pointer to zero-terminated comment or Z_NULL */
+ uInt comm_max; /* space at comment (only when reading header) */
+ int hcrc; /* true if there was or will be a header crc */
+ int done; /* true when done reading gzip header (not used
+ when writing a gzip file) */
+} gz_header;
+
+typedef gz_header FAR *gz_headerp;
+
+/*
+ The application must update next_in and avail_in when avail_in has dropped
+ to zero. It must update next_out and avail_out when avail_out has dropped
+ to zero. The application must initialize zalloc, zfree and opaque before
+ calling the init function. All other fields are set by the compression
+ library and must not be updated by the application.
+
+ The opaque value provided by the application will be passed as the first
+ parameter for calls of zalloc and zfree. This can be useful for custom
+ memory management. The compression library attaches no meaning to the
+ opaque value.
+
+ zalloc must return Z_NULL if there is not enough memory for the object.
+ If zlib is used in a multi-threaded application, zalloc and zfree must be
+ thread safe.
+
+ On 16-bit systems, the functions zalloc and zfree must be able to allocate
+ exactly 65536 bytes, but will not be required to allocate more than this if
+ the symbol MAXSEG_64K is defined (see zconf.h). WARNING: On MSDOS, pointers
+ returned by zalloc for objects of exactly 65536 bytes *must* have their
+ offset normalized to zero. The default allocation function provided by this
+ library ensures this (see zutil.c). To reduce memory requirements and avoid
+ any allocation of 64K objects, at the expense of compression ratio, compile
+ the library with -DMAX_WBITS=14 (see zconf.h).
+
+ The fields total_in and total_out can be used for statistics or progress
+ reports. After compression, total_in holds the total size of the
+ uncompressed data and may be saved for use in the decompressor (particularly
+ if the decompressor wants to decompress everything in a single step).
+*/
+
+ /* constants */
+
+#define Z_NO_FLUSH 0
+#define Z_PARTIAL_FLUSH 1
+#define Z_SYNC_FLUSH 2
+#define Z_FULL_FLUSH 3
+#define Z_FINISH 4
+#define Z_BLOCK 5
+#define Z_TREES 6
+/* Allowed flush values; see deflate() and inflate() below for details */
+
+#define Z_OK 0
+#define Z_STREAM_END 1
+#define Z_NEED_DICT 2
+#define Z_ERRNO (-1)
+#define Z_STREAM_ERROR (-2)
+#define Z_DATA_ERROR (-3)
+#define Z_MEM_ERROR (-4)
+#define Z_BUF_ERROR (-5)
+#define Z_VERSION_ERROR (-6)
+/* Return codes for the compression/decompression functions. Negative values
+ * are errors, positive values are used for special but normal events.
+ */
+
+#define Z_NO_COMPRESSION 0
+#define Z_BEST_SPEED 1
+#define Z_BEST_COMPRESSION 9
+#define Z_DEFAULT_COMPRESSION (-1)
+/* compression levels */
+
+#define Z_FILTERED 1
+#define Z_HUFFMAN_ONLY 2
+#define Z_RLE 3
+#define Z_FIXED 4
+#define Z_DEFAULT_STRATEGY 0
+/* compression strategy; see deflateInit2() below for details */
+
+#define Z_BINARY 0
+#define Z_TEXT 1
+#define Z_ASCII Z_TEXT /* for compatibility with 1.2.2 and earlier */
+#define Z_UNKNOWN 2
+/* Possible values of the data_type field (though see inflate()) */
+
+#define Z_DEFLATED 8
+/* The deflate compression method (the only one supported in this version) */
+
+#define Z_NULL 0 /* for initializing zalloc, zfree, opaque */
+
+#define zlib_version zlibVersion()
+/* for compatibility with versions < 1.0.2 */
+
+
+ /* basic functions */
+
+ZEXTERN const char * ZEXPORT zlibVersion OF((void));
+/* The application can compare zlibVersion and ZLIB_VERSION for consistency.
+ If the first character differs, the library code actually used is not
+ compatible with the zlib.h header file used by the application. This check
+ is automatically made by deflateInit and inflateInit.
+ */
+
+/*
+ZEXTERN int ZEXPORT deflateInit OF((z_streamp strm, int level));
+
+ Initializes the internal stream state for compression. The fields
+ zalloc, zfree and opaque must be initialized before by the caller. If
+ zalloc and zfree are set to Z_NULL, deflateInit updates them to use default
+ allocation functions.
+
+ The compression level must be Z_DEFAULT_COMPRESSION, or between 0 and 9:
+ 1 gives best speed, 9 gives best compression, 0 gives no compression at all
+ (the input data is simply copied a block at a time). Z_DEFAULT_COMPRESSION
+ requests a default compromise between speed and compression (currently
+ equivalent to level 6).
+
+ deflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough
+ memory, Z_STREAM_ERROR if level is not a valid compression level, or
+ Z_VERSION_ERROR if the zlib library version (zlib_version) is incompatible
+ with the version assumed by the caller (ZLIB_VERSION). msg is set to null
+ if there is no error message. deflateInit does not perform any compression:
+ this will be done by deflate().
+*/
+
+
+ZEXTERN int ZEXPORT deflate OF((z_streamp strm, int flush));
+/*
+ deflate compresses as much data as possible, and stops when the input
+ buffer becomes empty or the output buffer becomes full. It may introduce
+ some output latency (reading input without producing any output) except when
+ forced to flush.
+
+ The detailed semantics are as follows. deflate performs one or both of the
+ following actions:
+
+ - Compress more input starting at next_in and update next_in and avail_in
+ accordingly. If not all input can be processed (because there is not
+ enough room in the output buffer), next_in and avail_in are updated and
+ processing will resume at this point for the next call of deflate().
+
+ - Provide more output starting at next_out and update next_out and avail_out
+ accordingly. This action is forced if the parameter flush is non zero.
+ Forcing flush frequently degrades the compression ratio, so this parameter
+ should be set only when necessary (in interactive applications). Some
+ output may be provided even if flush is not set.
+
+ Before the call of deflate(), the application should ensure that at least
+ one of the actions is possible, by providing more input and/or consuming more
+ output, and updating avail_in or avail_out accordingly; avail_out should
+ never be zero before the call. The application can consume the compressed
+ output when it wants, for example when the output buffer is full (avail_out
+ == 0), or after each call of deflate(). If deflate returns Z_OK and with
+ zero avail_out, it must be called again after making room in the output
+ buffer because there might be more output pending.
+
+ Normally the parameter flush is set to Z_NO_FLUSH, which allows deflate to
+ decide how much data to accumulate before producing output, in order to
+ maximize compression.
+
+ If the parameter flush is set to Z_SYNC_FLUSH, all pending output is
+ flushed to the output buffer and the output is aligned on a byte boundary, so
+ that the decompressor can get all input data available so far. (In
+ particular avail_in is zero after the call if enough output space has been
+ provided before the call.) Flushing may degrade compression for some
+ compression algorithms and so it should be used only when necessary. This
+ completes the current deflate block and follows it with an empty stored block
+ that is three bits plus filler bits to the next byte, followed by four bytes
+ (00 00 ff ff).
+
+ If flush is set to Z_PARTIAL_FLUSH, all pending output is flushed to the
+ output buffer, but the output is not aligned to a byte boundary. All of the
+ input data so far will be available to the decompressor, as for Z_SYNC_FLUSH.
+ This completes the current deflate block and follows it with an empty fixed
+ codes block that is 10 bits long. This assures that enough bytes are output
+ in order for the decompressor to finish the block before the empty fixed code
+ block.
+
+ If flush is set to Z_BLOCK, a deflate block is completed and emitted, as
+ for Z_SYNC_FLUSH, but the output is not aligned on a byte boundary, and up to
+ seven bits of the current block are held to be written as the next byte after
+ the next deflate block is completed. In this case, the decompressor may not
+ be provided enough bits at this point in order to complete decompression of
+ the data provided so far to the compressor. It may need to wait for the next
+ block to be emitted. This is for advanced applications that need to control
+ the emission of deflate blocks.
+
+ If flush is set to Z_FULL_FLUSH, all output is flushed as with
+ Z_SYNC_FLUSH, and the compression state is reset so that decompression can
+ restart from this point if previous compressed data has been damaged or if
+ random access is desired. Using Z_FULL_FLUSH too often can seriously degrade
+ compression.
+
+ If deflate returns with avail_out == 0, this function must be called again
+ with the same value of the flush parameter and more output space (updated
+ avail_out), until the flush is complete (deflate returns with non-zero
+ avail_out). In the case of a Z_FULL_FLUSH or Z_SYNC_FLUSH, make sure that
+ avail_out is greater than six to avoid repeated flush markers due to
+ avail_out == 0 on return.
+
+ If the parameter flush is set to Z_FINISH, pending input is processed,
+ pending output is flushed and deflate returns with Z_STREAM_END if there was
+ enough output space; if deflate returns with Z_OK, this function must be
+ called again with Z_FINISH and more output space (updated avail_out) but no
+ more input data, until it returns with Z_STREAM_END or an error. After
+ deflate has returned Z_STREAM_END, the only possible operations on the stream
+ are deflateReset or deflateEnd.
+
+ Z_FINISH can be used immediately after deflateInit if all the compression
+ is to be done in a single step. In this case, avail_out must be at least the
+ value returned by deflateBound (see below). Then deflate is guaranteed to
+ return Z_STREAM_END. If not enough output space is provided, deflate will
+ not return Z_STREAM_END, and it must be called again as described above.
+
+ deflate() sets strm->adler to the adler32 checksum of all input read
+ so far (that is, total_in bytes).
+
+ deflate() may update strm->data_type if it can make a good guess about
+ the input data type (Z_BINARY or Z_TEXT). In doubt, the data is considered
+ binary. This field is only for information purposes and does not affect the
+ compression algorithm in any manner.
+
+ deflate() returns Z_OK if some progress has been made (more input
+ processed or more output produced), Z_STREAM_END if all input has been
+ consumed and all output has been produced (only when flush is set to
+ Z_FINISH), Z_STREAM_ERROR if the stream state was inconsistent (for example
+ if next_in or next_out was Z_NULL), Z_BUF_ERROR if no progress is possible
+ (for example avail_in or avail_out was zero). Note that Z_BUF_ERROR is not
+ fatal, and deflate() can be called again with more input and more output
+ space to continue compressing.
+*/
+
+
+ZEXTERN int ZEXPORT deflateEnd OF((z_streamp strm));
+/*
+ All dynamically allocated data structures for this stream are freed.
+ This function discards any unprocessed input and does not flush any pending
+ output.
+
+ deflateEnd returns Z_OK if success, Z_STREAM_ERROR if the
+ stream state was inconsistent, Z_DATA_ERROR if the stream was freed
+ prematurely (some input or output was discarded). In the error case, msg
+ may be set but then points to a static string (which must not be
+ deallocated).
+*/
+
+
+/*
+ZEXTERN int ZEXPORT inflateInit OF((z_streamp strm));
+
+ Initializes the internal stream state for decompression. The fields
+ next_in, avail_in, zalloc, zfree and opaque must be initialized before by
+ the caller. If next_in is not Z_NULL and avail_in is large enough (the
+ exact value depends on the compression method), inflateInit determines the
+ compression method from the zlib header and allocates all data structures
+ accordingly; otherwise the allocation will be deferred to the first call of
+ inflate. If zalloc and zfree are set to Z_NULL, inflateInit updates them to
+ use default allocation functions.
+
+ inflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough
+ memory, Z_VERSION_ERROR if the zlib library version is incompatible with the
+ version assumed by the caller, or Z_STREAM_ERROR if the parameters are
+ invalid, such as a null pointer to the structure. msg is set to null if
+ there is no error message. inflateInit does not perform any decompression
+ apart from possibly reading the zlib header if present: actual decompression
+ will be done by inflate(). (So next_in and avail_in may be modified, but
+ next_out and avail_out are unused and unchanged.) The current implementation
+ of inflateInit() does not process any header information -- that is deferred
+ until inflate() is called.
+*/
+
+
+ZEXTERN int ZEXPORT inflate OF((z_streamp strm, int flush));
+/*
+ inflate decompresses as much data as possible, and stops when the input
+ buffer becomes empty or the output buffer becomes full. It may introduce
+ some output latency (reading input without producing any output) except when
+ forced to flush.
+
+ The detailed semantics are as follows. inflate performs one or both of the
+ following actions:
+
+ - Decompress more input starting at next_in and update next_in and avail_in
+ accordingly. If not all input can be processed (because there is not
+ enough room in the output buffer), next_in is updated and processing will
+ resume at this point for the next call of inflate().
+
+ - Provide more output starting at next_out and update next_out and avail_out
+ accordingly. inflate() provides as much output as possible, until there is
+ no more input data or no more space in the output buffer (see below about
+ the flush parameter).
+
+ Before the call of inflate(), the application should ensure that at least
+ one of the actions is possible, by providing more input and/or consuming more
+ output, and updating the next_* and avail_* values accordingly. The
+ application can consume the uncompressed output when it wants, for example
+ when the output buffer is full (avail_out == 0), or after each call of
+ inflate(). If inflate returns Z_OK and with zero avail_out, it must be
+ called again after making room in the output buffer because there might be
+ more output pending.
+
+ The flush parameter of inflate() can be Z_NO_FLUSH, Z_SYNC_FLUSH, Z_FINISH,
+ Z_BLOCK, or Z_TREES. Z_SYNC_FLUSH requests that inflate() flush as much
+ output as possible to the output buffer. Z_BLOCK requests that inflate()
+ stop if and when it gets to the next deflate block boundary. When decoding
+ the zlib or gzip format, this will cause inflate() to return immediately
+ after the header and before the first block. When doing a raw inflate,
+ inflate() will go ahead and process the first block, and will return when it
+ gets to the end of that block, or when it runs out of data.
+
+ The Z_BLOCK option assists in appending to or combining deflate streams.
+ Also to assist in this, on return inflate() will set strm->data_type to the
+ number of unused bits in the last byte taken from strm->next_in, plus 64 if
+ inflate() is currently decoding the last block in the deflate stream, plus
+ 128 if inflate() returned immediately after decoding an end-of-block code or
+ decoding the complete header up to just before the first byte of the deflate
+ stream. The end-of-block will not be indicated until all of the uncompressed
+ data from that block has been written to strm->next_out. The number of
+ unused bits may in general be greater than seven, except when bit 7 of
+ data_type is set, in which case the number of unused bits will be less than
+ eight. data_type is set as noted here every time inflate() returns for all
+ flush options, and so can be used to determine the amount of currently
+ consumed input in bits.
+
+ The Z_TREES option behaves as Z_BLOCK does, but it also returns when the
+ end of each deflate block header is reached, before any actual data in that
+ block is decoded. This allows the caller to determine the length of the
+ deflate block header for later use in random access within a deflate block.
+ 256 is added to the value of strm->data_type when inflate() returns
+ immediately after reaching the end of the deflate block header.
+
+ inflate() should normally be called until it returns Z_STREAM_END or an
+ error. However if all decompression is to be performed in a single step (a
+ single call of inflate), the parameter flush should be set to Z_FINISH. In
+ this case all pending input is processed and all pending output is flushed;
+ avail_out must be large enough to hold all of the uncompressed data for the
+ operation to complete. (The size of the uncompressed data may have been
+ saved by the compressor for this purpose.) The use of Z_FINISH is not
+ required to perform an inflation in one step. However it may be used to
+ inform inflate that a faster approach can be used for the single inflate()
+ call. Z_FINISH also informs inflate to not maintain a sliding window if the
+ stream completes, which reduces inflate's memory footprint. If the stream
+ does not complete, either because not all of the stream is provided or not
+ enough output space is provided, then a sliding window will be allocated and
+ inflate() can be called again to continue the operation as if Z_NO_FLUSH had
+ been used.
+
+ In this implementation, inflate() always flushes as much output as
+ possible to the output buffer, and always uses the faster approach on the
+ first call. So the effects of the flush parameter in this implementation are
+ on the return value of inflate() as noted below, when inflate() returns early
+ when Z_BLOCK or Z_TREES is used, and when inflate() avoids the allocation of
+ memory for a sliding window when Z_FINISH is used.
+
+ If a preset dictionary is needed after this call (see inflateSetDictionary
+ below), inflate sets strm->adler to the Adler-32 checksum of the dictionary
+ chosen by the compressor and returns Z_NEED_DICT; otherwise it sets
+ strm->adler to the Adler-32 checksum of all output produced so far (that is,
+ total_out bytes) and returns Z_OK, Z_STREAM_END or an error code as described
+ below. At the end of the stream, inflate() checks that its computed adler32
+ checksum is equal to that saved by the compressor and returns Z_STREAM_END
+ only if the checksum is correct.
+
+ inflate() can decompress and check either zlib-wrapped or gzip-wrapped
+ deflate data. The header type is detected automatically, if requested when
+ initializing with inflateInit2(). Any information contained in the gzip
+ header is not retained, so applications that need that information should
+ instead use raw inflate, see inflateInit2() below, or inflateBack() and
+ perform their own processing of the gzip header and trailer. When processing
+ gzip-wrapped deflate data, strm->adler32 is set to the CRC-32 of the output
+ producted so far. The CRC-32 is checked against the gzip trailer.
+
+ inflate() returns Z_OK if some progress has been made (more input processed
+ or more output produced), Z_STREAM_END if the end of the compressed data has
+ been reached and all uncompressed output has been produced, Z_NEED_DICT if a
+ preset dictionary is needed at this point, Z_DATA_ERROR if the input data was
+ corrupted (input stream not conforming to the zlib format or incorrect check
+ value), Z_STREAM_ERROR if the stream structure was inconsistent (for example
+ next_in or next_out was Z_NULL), Z_MEM_ERROR if there was not enough memory,
+ Z_BUF_ERROR if no progress is possible or if there was not enough room in the
+ output buffer when Z_FINISH is used. Note that Z_BUF_ERROR is not fatal, and
+ inflate() can be called again with more input and more output space to
+ continue decompressing. If Z_DATA_ERROR is returned, the application may
+ then call inflateSync() to look for a good compression block if a partial
+ recovery of the data is desired.
+*/
+
+
+ZEXTERN int ZEXPORT inflateEnd OF((z_streamp strm));
+/*
+ All dynamically allocated data structures for this stream are freed.
+ This function discards any unprocessed input and does not flush any pending
+ output.
+
+ inflateEnd returns Z_OK if success, Z_STREAM_ERROR if the stream state
+ was inconsistent. In the error case, msg may be set but then points to a
+ static string (which must not be deallocated).
+*/
+
+
+ /* Advanced functions */
+
+/*
+ The following functions are needed only in some special applications.
+*/
+
+/*
+ZEXTERN int ZEXPORT deflateInit2 OF((z_streamp strm,
+ int level,
+ int method,
+ int windowBits,
+ int memLevel,
+ int strategy));
+
+ This is another version of deflateInit with more compression options. The
+ fields next_in, zalloc, zfree and opaque must be initialized before by the
+ caller.
+
+ The method parameter is the compression method. It must be Z_DEFLATED in
+ this version of the library.
+
+ The windowBits parameter is the base two logarithm of the window size
+ (the size of the history buffer). It should be in the range 8..15 for this
+ version of the library. Larger values of this parameter result in better
+ compression at the expense of memory usage. The default value is 15 if
+ deflateInit is used instead.
+
+ windowBits can also be -8..-15 for raw deflate. In this case, -windowBits
+ determines the window size. deflate() will then generate raw deflate data
+ with no zlib header or trailer, and will not compute an adler32 check value.
+
+ windowBits can also be greater than 15 for optional gzip encoding. Add
+ 16 to windowBits to write a simple gzip header and trailer around the
+ compressed data instead of a zlib wrapper. The gzip header will have no
+ file name, no extra data, no comment, no modification time (set to zero), no
+ header crc, and the operating system will be set to 255 (unknown). If a
+ gzip stream is being written, strm->adler is a crc32 instead of an adler32.
+
+ The memLevel parameter specifies how much memory should be allocated
+ for the internal compression state. memLevel=1 uses minimum memory but is
+ slow and reduces compression ratio; memLevel=9 uses maximum memory for
+ optimal speed. The default value is 8. See zconf.h for total memory usage
+ as a function of windowBits and memLevel.
+
+ The strategy parameter is used to tune the compression algorithm. Use the
+ value Z_DEFAULT_STRATEGY for normal data, Z_FILTERED for data produced by a
+ filter (or predictor), Z_HUFFMAN_ONLY to force Huffman encoding only (no
+ string match), or Z_RLE to limit match distances to one (run-length
+ encoding). Filtered data consists mostly of small values with a somewhat
+ random distribution. In this case, the compression algorithm is tuned to
+ compress them better. The effect of Z_FILTERED is to force more Huffman
+ coding and less string matching; it is somewhat intermediate between
+ Z_DEFAULT_STRATEGY and Z_HUFFMAN_ONLY. Z_RLE is designed to be almost as
+ fast as Z_HUFFMAN_ONLY, but give better compression for PNG image data. The
+ strategy parameter only affects the compression ratio but not the
+ correctness of the compressed output even if it is not set appropriately.
+ Z_FIXED prevents the use of dynamic Huffman codes, allowing for a simpler
+ decoder for special applications.
+
+ deflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough
+ memory, Z_STREAM_ERROR if any parameter is invalid (such as an invalid
+ method), or Z_VERSION_ERROR if the zlib library version (zlib_version) is
+ incompatible with the version assumed by the caller (ZLIB_VERSION). msg is
+ set to null if there is no error message. deflateInit2 does not perform any
+ compression: this will be done by deflate().
+*/
+
+ZEXTERN int ZEXPORT deflateSetDictionary OF((z_streamp strm,
+ const Bytef *dictionary,
+ uInt dictLength));
+/*
+ Initializes the compression dictionary from the given byte sequence
+ without producing any compressed output. When using the zlib format, this
+ function must be called immediately after deflateInit, deflateInit2 or
+ deflateReset, and before any call of deflate. When doing raw deflate, this
+ function must be called either before any call of deflate, or immediately
+ after the completion of a deflate block, i.e. after all input has been
+ consumed and all output has been delivered when using any of the flush
+ options Z_BLOCK, Z_PARTIAL_FLUSH, Z_SYNC_FLUSH, or Z_FULL_FLUSH. The
+ compressor and decompressor must use exactly the same dictionary (see
+ inflateSetDictionary).
+
+ The dictionary should consist of strings (byte sequences) that are likely
+ to be encountered later in the data to be compressed, with the most commonly
+ used strings preferably put towards the end of the dictionary. Using a
+ dictionary is most useful when the data to be compressed is short and can be
+ predicted with good accuracy; the data can then be compressed better than
+ with the default empty dictionary.
+
+ Depending on the size of the compression data structures selected by
+ deflateInit or deflateInit2, a part of the dictionary may in effect be
+ discarded, for example if the dictionary is larger than the window size
+ provided in deflateInit or deflateInit2. Thus the strings most likely to be
+ useful should be put at the end of the dictionary, not at the front. In
+ addition, the current implementation of deflate will use at most the window
+ size minus 262 bytes of the provided dictionary.
+
+ Upon return of this function, strm->adler is set to the adler32 value
+ of the dictionary; the decompressor may later use this value to determine
+ which dictionary has been used by the compressor. (The adler32 value
+ applies to the whole dictionary even if only a subset of the dictionary is
+ actually used by the compressor.) If a raw deflate was requested, then the
+ adler32 value is not computed and strm->adler is not set.
+
+ deflateSetDictionary returns Z_OK if success, or Z_STREAM_ERROR if a
+ parameter is invalid (e.g. dictionary being Z_NULL) or the stream state is
+ inconsistent (for example if deflate has already been called for this stream
+ or if not at a block boundary for raw deflate). deflateSetDictionary does
+ not perform any compression: this will be done by deflate().
+*/
+
+ZEXTERN int ZEXPORT deflateCopy OF((z_streamp dest,
+ z_streamp source));
+/*
+ Sets the destination stream as a complete copy of the source stream.
+
+ This function can be useful when several compression strategies will be
+ tried, for example when there are several ways of pre-processing the input
+ data with a filter. The streams that will be discarded should then be freed
+ by calling deflateEnd. Note that deflateCopy duplicates the internal
+ compression state which can be quite large, so this strategy is slow and can
+ consume lots of memory.
+
+ deflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not
+ enough memory, Z_STREAM_ERROR if the source stream state was inconsistent
+ (such as zalloc being Z_NULL). msg is left unchanged in both source and
+ destination.
+*/
+
+ZEXTERN int ZEXPORT deflateReset OF((z_streamp strm));
+/*
+ This function is equivalent to deflateEnd followed by deflateInit,
+ but does not free and reallocate all the internal compression state. The
+ stream will keep the same compression level and any other attributes that
+ may have been set by deflateInit2.
+
+ deflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source
+ stream state was inconsistent (such as zalloc or state being Z_NULL).
+*/
+
+ZEXTERN int ZEXPORT deflateParams OF((z_streamp strm,
+ int level,
+ int strategy));
+/*
+ Dynamically update the compression level and compression strategy. The
+ interpretation of level and strategy is as in deflateInit2. This can be
+ used to switch between compression and straight copy of the input data, or
+ to switch to a different kind of input data requiring a different strategy.
+ If the compression level is changed, the input available so far is
+ compressed with the old level (and may be flushed); the new level will take
+ effect only at the next call of deflate().
+
+ Before the call of deflateParams, the stream state must be set as for
+ a call of deflate(), since the currently available input may have to be
+ compressed and flushed. In particular, strm->avail_out must be non-zero.
+
+ deflateParams returns Z_OK if success, Z_STREAM_ERROR if the source
+ stream state was inconsistent or if a parameter was invalid, Z_BUF_ERROR if
+ strm->avail_out was zero.
+*/
+
+ZEXTERN int ZEXPORT deflateTune OF((z_streamp strm,
+ int good_length,
+ int max_lazy,
+ int nice_length,
+ int max_chain));
+/*
+ Fine tune deflate's internal compression parameters. This should only be
+ used by someone who understands the algorithm used by zlib's deflate for
+ searching for the best matching string, and even then only by the most
+ fanatic optimizer trying to squeeze out the last compressed bit for their
+ specific input data. Read the deflate.c source code for the meaning of the
+ max_lazy, good_length, nice_length, and max_chain parameters.
+
+ deflateTune() can be called after deflateInit() or deflateInit2(), and
+ returns Z_OK on success, or Z_STREAM_ERROR for an invalid deflate stream.
+ */
+
+ZEXTERN uLong ZEXPORT deflateBound OF((z_streamp strm,
+ uLong sourceLen));
+/*
+ deflateBound() returns an upper bound on the compressed size after
+ deflation of sourceLen bytes. It must be called after deflateInit() or
+ deflateInit2(), and after deflateSetHeader(), if used. This would be used
+ to allocate an output buffer for deflation in a single pass, and so would be
+ called before deflate(). If that first deflate() call is provided the
+ sourceLen input bytes, an output buffer allocated to the size returned by
+ deflateBound(), and the flush value Z_FINISH, then deflate() is guaranteed
+ to return Z_STREAM_END. Note that it is possible for the compressed size to
+ be larger than the value returned by deflateBound() if flush options other
+ than Z_FINISH or Z_NO_FLUSH are used.
+*/
+
+ZEXTERN int ZEXPORT deflatePending OF((z_streamp strm,
+ unsigned *pending,
+ int *bits));
+/*
+ deflatePending() returns the number of bytes and bits of output that have
+ been generated, but not yet provided in the available output. The bytes not
+ provided would be due to the available output space having being consumed.
+ The number of bits of output not provided are between 0 and 7, where they
+ await more bits to join them in order to fill out a full byte. If pending
+ or bits are Z_NULL, then those values are not set.
+
+ deflatePending returns Z_OK if success, or Z_STREAM_ERROR if the source
+ stream state was inconsistent.
+ */
+
+ZEXTERN int ZEXPORT deflatePrime OF((z_streamp strm,
+ int bits,
+ int value));
+/*
+ deflatePrime() inserts bits in the deflate output stream. The intent
+ is that this function is used to start off the deflate output with the bits
+ leftover from a previous deflate stream when appending to it. As such, this
+ function can only be used for raw deflate, and must be used before the first
+ deflate() call after a deflateInit2() or deflateReset(). bits must be less
+ than or equal to 16, and that many of the least significant bits of value
+ will be inserted in the output.
+
+ deflatePrime returns Z_OK if success, Z_BUF_ERROR if there was not enough
+ room in the internal buffer to insert the bits, or Z_STREAM_ERROR if the
+ source stream state was inconsistent.
+*/
+
+ZEXTERN int ZEXPORT deflateSetHeader OF((z_streamp strm,
+ gz_headerp head));
+/*
+ deflateSetHeader() provides gzip header information for when a gzip
+ stream is requested by deflateInit2(). deflateSetHeader() may be called
+ after deflateInit2() or deflateReset() and before the first call of
+ deflate(). The text, time, os, extra field, name, and comment information
+ in the provided gz_header structure are written to the gzip header (xflag is
+ ignored -- the extra flags are set according to the compression level). The
+ caller must assure that, if not Z_NULL, name and comment are terminated with
+ a zero byte, and that if extra is not Z_NULL, that extra_len bytes are
+ available there. If hcrc is true, a gzip header crc is included. Note that
+ the current versions of the command-line version of gzip (up through version
+ 1.3.x) do not support header crc's, and will report that it is a "multi-part
+ gzip file" and give up.
+
+ If deflateSetHeader is not used, the default gzip header has text false,
+ the time set to zero, and os set to 255, with no extra, name, or comment
+ fields. The gzip header is returned to the default state by deflateReset().
+
+ deflateSetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source
+ stream state was inconsistent.
+*/
+
+/*
+ZEXTERN int ZEXPORT inflateInit2 OF((z_streamp strm,
+ int windowBits));
+
+ This is another version of inflateInit with an extra parameter. The
+ fields next_in, avail_in, zalloc, zfree and opaque must be initialized
+ before by the caller.
+
+ The windowBits parameter is the base two logarithm of the maximum window
+ size (the size of the history buffer). It should be in the range 8..15 for
+ this version of the library. The default value is 15 if inflateInit is used
+ instead. windowBits must be greater than or equal to the windowBits value
+ provided to deflateInit2() while compressing, or it must be equal to 15 if
+ deflateInit2() was not used. If a compressed stream with a larger window
+ size is given as input, inflate() will return with the error code
+ Z_DATA_ERROR instead of trying to allocate a larger window.
+
+ windowBits can also be zero to request that inflate use the window size in
+ the zlib header of the compressed stream.
+
+ windowBits can also be -8..-15 for raw inflate. In this case, -windowBits
+ determines the window size. inflate() will then process raw deflate data,
+ not looking for a zlib or gzip header, not generating a check value, and not
+ looking for any check values for comparison at the end of the stream. This
+ is for use with other formats that use the deflate compressed data format
+ such as zip. Those formats provide their own check values. If a custom
+ format is developed using the raw deflate format for compressed data, it is
+ recommended that a check value such as an adler32 or a crc32 be applied to
+ the uncompressed data as is done in the zlib, gzip, and zip formats. For
+ most applications, the zlib format should be used as is. Note that comments
+ above on the use in deflateInit2() applies to the magnitude of windowBits.
+
+ windowBits can also be greater than 15 for optional gzip decoding. Add
+ 32 to windowBits to enable zlib and gzip decoding with automatic header
+ detection, or add 16 to decode only the gzip format (the zlib format will
+ return a Z_DATA_ERROR). If a gzip stream is being decoded, strm->adler is a
+ crc32 instead of an adler32.
+
+ inflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough
+ memory, Z_VERSION_ERROR if the zlib library version is incompatible with the
+ version assumed by the caller, or Z_STREAM_ERROR if the parameters are
+ invalid, such as a null pointer to the structure. msg is set to null if
+ there is no error message. inflateInit2 does not perform any decompression
+ apart from possibly reading the zlib header if present: actual decompression
+ will be done by inflate(). (So next_in and avail_in may be modified, but
+ next_out and avail_out are unused and unchanged.) The current implementation
+ of inflateInit2() does not process any header information -- that is
+ deferred until inflate() is called.
+*/
+
+ZEXTERN int ZEXPORT inflateSetDictionary OF((z_streamp strm,
+ const Bytef *dictionary,
+ uInt dictLength));
+/*
+ Initializes the decompression dictionary from the given uncompressed byte
+ sequence. This function must be called immediately after a call of inflate,
+ if that call returned Z_NEED_DICT. The dictionary chosen by the compressor
+ can be determined from the adler32 value returned by that call of inflate.
+ The compressor and decompressor must use exactly the same dictionary (see
+ deflateSetDictionary). For raw inflate, this function can be called at any
+ time to set the dictionary. If the provided dictionary is smaller than the
+ window and there is already data in the window, then the provided dictionary
+ will amend what's there. The application must insure that the dictionary
+ that was used for compression is provided.
+
+ inflateSetDictionary returns Z_OK if success, Z_STREAM_ERROR if a
+ parameter is invalid (e.g. dictionary being Z_NULL) or the stream state is
+ inconsistent, Z_DATA_ERROR if the given dictionary doesn't match the
+ expected one (incorrect adler32 value). inflateSetDictionary does not
+ perform any decompression: this will be done by subsequent calls of
+ inflate().
+*/
+
+ZEXTERN int ZEXPORT inflateGetDictionary OF((z_streamp strm,
+ Bytef *dictionary,
+ uInt *dictLength));
+/*
+ Returns the sliding dictionary being maintained by inflate. dictLength is
+ set to the number of bytes in the dictionary, and that many bytes are copied
+ to dictionary. dictionary must have enough space, where 32768 bytes is
+ always enough. If inflateGetDictionary() is called with dictionary equal to
+ Z_NULL, then only the dictionary length is returned, and nothing is copied.
+ Similary, if dictLength is Z_NULL, then it is not set.
+
+ inflateGetDictionary returns Z_OK on success, or Z_STREAM_ERROR if the
+ stream state is inconsistent.
+*/
+
+ZEXTERN int ZEXPORT inflateSync OF((z_streamp strm));
+/*
+ Skips invalid compressed data until a possible full flush point (see above
+ for the description of deflate with Z_FULL_FLUSH) can be found, or until all
+ available input is skipped. No output is provided.
+
+ inflateSync searches for a 00 00 FF FF pattern in the compressed data.
+ All full flush points have this pattern, but not all occurrences of this
+ pattern are full flush points.
+
+ inflateSync returns Z_OK if a possible full flush point has been found,
+ Z_BUF_ERROR if no more input was provided, Z_DATA_ERROR if no flush point
+ has been found, or Z_STREAM_ERROR if the stream structure was inconsistent.
+ In the success case, the application may save the current current value of
+ total_in which indicates where valid compressed data was found. In the
+ error case, the application may repeatedly call inflateSync, providing more
+ input each time, until success or end of the input data.
+*/
+
+ZEXTERN int ZEXPORT inflateCopy OF((z_streamp dest,
+ z_streamp source));
+/*
+ Sets the destination stream as a complete copy of the source stream.
+
+ This function can be useful when randomly accessing a large stream. The
+ first pass through the stream can periodically record the inflate state,
+ allowing restarting inflate at those points when randomly accessing the
+ stream.
+
+ inflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not
+ enough memory, Z_STREAM_ERROR if the source stream state was inconsistent
+ (such as zalloc being Z_NULL). msg is left unchanged in both source and
+ destination.
+*/
+
+ZEXTERN int ZEXPORT inflateReset OF((z_streamp strm));
+/*
+ This function is equivalent to inflateEnd followed by inflateInit,
+ but does not free and reallocate all the internal decompression state. The
+ stream will keep attributes that may have been set by inflateInit2.
+
+ inflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source
+ stream state was inconsistent (such as zalloc or state being Z_NULL).
+*/
+
+ZEXTERN int ZEXPORT inflateReset2 OF((z_streamp strm,
+ int windowBits));
+/*
+ This function is the same as inflateReset, but it also permits changing
+ the wrap and window size requests. The windowBits parameter is interpreted
+ the same as it is for inflateInit2.
+
+ inflateReset2 returns Z_OK if success, or Z_STREAM_ERROR if the source
+ stream state was inconsistent (such as zalloc or state being Z_NULL), or if
+ the windowBits parameter is invalid.
+*/
+
+ZEXTERN int ZEXPORT inflatePrime OF((z_streamp strm,
+ int bits,
+ int value));
+/*
+ This function inserts bits in the inflate input stream. The intent is
+ that this function is used to start inflating at a bit position in the
+ middle of a byte. The provided bits will be used before any bytes are used
+ from next_in. This function should only be used with raw inflate, and
+ should be used before the first inflate() call after inflateInit2() or
+ inflateReset(). bits must be less than or equal to 16, and that many of the
+ least significant bits of value will be inserted in the input.
+
+ If bits is negative, then the input stream bit buffer is emptied. Then
+ inflatePrime() can be called again to put bits in the buffer. This is used
+ to clear out bits leftover after feeding inflate a block description prior
+ to feeding inflate codes.
+
+ inflatePrime returns Z_OK if success, or Z_STREAM_ERROR if the source
+ stream state was inconsistent.
+*/
+
+ZEXTERN long ZEXPORT inflateMark OF((z_streamp strm));
+/*
+ This function returns two values, one in the lower 16 bits of the return
+ value, and the other in the remaining upper bits, obtained by shifting the
+ return value down 16 bits. If the upper value is -1 and the lower value is
+ zero, then inflate() is currently decoding information outside of a block.
+ If the upper value is -1 and the lower value is non-zero, then inflate is in
+ the middle of a stored block, with the lower value equaling the number of
+ bytes from the input remaining to copy. If the upper value is not -1, then
+ it is the number of bits back from the current bit position in the input of
+ the code (literal or length/distance pair) currently being processed. In
+ that case the lower value is the number of bytes already emitted for that
+ code.
+
+ A code is being processed if inflate is waiting for more input to complete
+ decoding of the code, or if it has completed decoding but is waiting for
+ more output space to write the literal or match data.
+
+ inflateMark() is used to mark locations in the input data for random
+ access, which may be at bit positions, and to note those cases where the
+ output of a code may span boundaries of random access blocks. The current
+ location in the input stream can be determined from avail_in and data_type
+ as noted in the description for the Z_BLOCK flush parameter for inflate.
+
+ inflateMark returns the value noted above or -1 << 16 if the provided
+ source stream state was inconsistent.
+*/
+
+ZEXTERN int ZEXPORT inflateGetHeader OF((z_streamp strm,
+ gz_headerp head));
+/*
+ inflateGetHeader() requests that gzip header information be stored in the
+ provided gz_header structure. inflateGetHeader() may be called after
+ inflateInit2() or inflateReset(), and before the first call of inflate().
+ As inflate() processes the gzip stream, head->done is zero until the header
+ is completed, at which time head->done is set to one. If a zlib stream is
+ being decoded, then head->done is set to -1 to indicate that there will be
+ no gzip header information forthcoming. Note that Z_BLOCK or Z_TREES can be
+ used to force inflate() to return immediately after header processing is
+ complete and before any actual data is decompressed.
+
+ The text, time, xflags, and os fields are filled in with the gzip header
+ contents. hcrc is set to true if there is a header CRC. (The header CRC
+ was valid if done is set to one.) If extra is not Z_NULL, then extra_max
+ contains the maximum number of bytes to write to extra. Once done is true,
+ extra_len contains the actual extra field length, and extra contains the
+ extra field, or that field truncated if extra_max is less than extra_len.
+ If name is not Z_NULL, then up to name_max characters are written there,
+ terminated with a zero unless the length is greater than name_max. If
+ comment is not Z_NULL, then up to comm_max characters are written there,
+ terminated with a zero unless the length is greater than comm_max. When any
+ of extra, name, or comment are not Z_NULL and the respective field is not
+ present in the header, then that field is set to Z_NULL to signal its
+ absence. This allows the use of deflateSetHeader() with the returned
+ structure to duplicate the header. However if those fields are set to
+ allocated memory, then the application will need to save those pointers
+ elsewhere so that they can be eventually freed.
+
+ If inflateGetHeader is not used, then the header information is simply
+ discarded. The header is always checked for validity, including the header
+ CRC if present. inflateReset() will reset the process to discard the header
+ information. The application would need to call inflateGetHeader() again to
+ retrieve the header from the next gzip stream.
+
+ inflateGetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source
+ stream state was inconsistent.
+*/
+
+/*
+ZEXTERN int ZEXPORT inflateBackInit OF((z_streamp strm, int windowBits,
+ unsigned char FAR *window));
+
+ Initialize the internal stream state for decompression using inflateBack()
+ calls. The fields zalloc, zfree and opaque in strm must be initialized
+ before the call. If zalloc and zfree are Z_NULL, then the default library-
+ derived memory allocation routines are used. windowBits is the base two
+ logarithm of the window size, in the range 8..15. window is a caller
+ supplied buffer of that size. Except for special applications where it is
+ assured that deflate was used with small window sizes, windowBits must be 15
+ and a 32K byte window must be supplied to be able to decompress general
+ deflate streams.
+
+ See inflateBack() for the usage of these routines.
+
+ inflateBackInit will return Z_OK on success, Z_STREAM_ERROR if any of
+ the parameters are invalid, Z_MEM_ERROR if the internal state could not be
+ allocated, or Z_VERSION_ERROR if the version of the library does not match
+ the version of the header file.
+*/
+
+typedef unsigned (*in_func) OF((void FAR *,
+ z_const unsigned char FAR * FAR *));
+typedef int (*out_func) OF((void FAR *, unsigned char FAR *, unsigned));
+
+ZEXTERN int ZEXPORT inflateBack OF((z_streamp strm,
+ in_func in, void FAR *in_desc,
+ out_func out, void FAR *out_desc));
+/*
+ inflateBack() does a raw inflate with a single call using a call-back
+ interface for input and output. This is potentially more efficient than
+ inflate() for file i/o applications, in that it avoids copying between the
+ output and the sliding window by simply making the window itself the output
+ buffer. inflate() can be faster on modern CPUs when used with large
+ buffers. inflateBack() trusts the application to not change the output
+ buffer passed by the output function, at least until inflateBack() returns.
+
+ inflateBackInit() must be called first to allocate the internal state
+ and to initialize the state with the user-provided window buffer.
+ inflateBack() may then be used multiple times to inflate a complete, raw
+ deflate stream with each call. inflateBackEnd() is then called to free the
+ allocated state.
+
+ A raw deflate stream is one with no zlib or gzip header or trailer.
+ This routine would normally be used in a utility that reads zip or gzip
+ files and writes out uncompressed files. The utility would decode the
+ header and process the trailer on its own, hence this routine expects only
+ the raw deflate stream to decompress. This is different from the normal
+ behavior of inflate(), which expects either a zlib or gzip header and
+ trailer around the deflate stream.
+
+ inflateBack() uses two subroutines supplied by the caller that are then
+ called by inflateBack() for input and output. inflateBack() calls those
+ routines until it reads a complete deflate stream and writes out all of the
+ uncompressed data, or until it encounters an error. The function's
+ parameters and return types are defined above in the in_func and out_func
+ typedefs. inflateBack() will call in(in_desc, &buf) which should return the
+ number of bytes of provided input, and a pointer to that input in buf. If
+ there is no input available, in() must return zero--buf is ignored in that
+ case--and inflateBack() will return a buffer error. inflateBack() will call
+ out(out_desc, buf, len) to write the uncompressed data buf[0..len-1]. out()
+ should return zero on success, or non-zero on failure. If out() returns
+ non-zero, inflateBack() will return with an error. Neither in() nor out()
+ are permitted to change the contents of the window provided to
+ inflateBackInit(), which is also the buffer that out() uses to write from.
+ The length written by out() will be at most the window size. Any non-zero
+ amount of input may be provided by in().
+
+ For convenience, inflateBack() can be provided input on the first call by
+ setting strm->next_in and strm->avail_in. If that input is exhausted, then
+ in() will be called. Therefore strm->next_in must be initialized before
+ calling inflateBack(). If strm->next_in is Z_NULL, then in() will be called
+ immediately for input. If strm->next_in is not Z_NULL, then strm->avail_in
+ must also be initialized, and then if strm->avail_in is not zero, input will
+ initially be taken from strm->next_in[0 .. strm->avail_in - 1].
+
+ The in_desc and out_desc parameters of inflateBack() is passed as the
+ first parameter of in() and out() respectively when they are called. These
+ descriptors can be optionally used to pass any information that the caller-
+ supplied in() and out() functions need to do their job.
+
+ On return, inflateBack() will set strm->next_in and strm->avail_in to
+ pass back any unused input that was provided by the last in() call. The
+ return values of inflateBack() can be Z_STREAM_END on success, Z_BUF_ERROR
+ if in() or out() returned an error, Z_DATA_ERROR if there was a format error
+ in the deflate stream (in which case strm->msg is set to indicate the nature
+ of the error), or Z_STREAM_ERROR if the stream was not properly initialized.
+ In the case of Z_BUF_ERROR, an input or output error can be distinguished
+ using strm->next_in which will be Z_NULL only if in() returned an error. If
+ strm->next_in is not Z_NULL, then the Z_BUF_ERROR was due to out() returning
+ non-zero. (in() will always be called before out(), so strm->next_in is
+ assured to be defined if out() returns non-zero.) Note that inflateBack()
+ cannot return Z_OK.
+*/
+
+ZEXTERN int ZEXPORT inflateBackEnd OF((z_streamp strm));
+/*
+ All memory allocated by inflateBackInit() is freed.
+
+ inflateBackEnd() returns Z_OK on success, or Z_STREAM_ERROR if the stream
+ state was inconsistent.
+*/
+
+ZEXTERN uLong ZEXPORT zlibCompileFlags OF((void));
+/* Return flags indicating compile-time options.
+
+ Type sizes, two bits each, 00 = 16 bits, 01 = 32, 10 = 64, 11 = other:
+ 1.0: size of uInt
+ 3.2: size of uLong
+ 5.4: size of voidpf (pointer)
+ 7.6: size of z_off_t
+
+ Compiler, assembler, and debug options:
+ 8: DEBUG
+ 9: ASMV or ASMINF -- use ASM code
+ 10: ZLIB_WINAPI -- exported functions use the WINAPI calling convention
+ 11: 0 (reserved)
+
+ One-time table building (smaller code, but not thread-safe if true):
+ 12: BUILDFIXED -- build static block decoding tables when needed
+ 13: DYNAMIC_CRC_TABLE -- build CRC calculation tables when needed
+ 14,15: 0 (reserved)
+
+ Library content (indicates missing functionality):
+ 16: NO_GZCOMPRESS -- gz* functions cannot compress (to avoid linking
+ deflate code when not needed)
+ 17: NO_GZIP -- deflate can't write gzip streams, and inflate can't detect
+ and decode gzip streams (to avoid linking crc code)
+ 18-19: 0 (reserved)
+
+ Operation variations (changes in library functionality):
+ 20: PKZIP_BUG_WORKAROUND -- slightly more permissive inflate
+ 21: FASTEST -- deflate algorithm with only one, lowest compression level
+ 22,23: 0 (reserved)
+
+ The sprintf variant used by gzprintf (zero is best):
+ 24: 0 = vs*, 1 = s* -- 1 means limited to 20 arguments after the format
+ 25: 0 = *nprintf, 1 = *printf -- 1 means gzprintf() not secure!
+ 26: 0 = returns value, 1 = void -- 1 means inferred string length returned
+
+ Remainder:
+ 27-31: 0 (reserved)
+ */
+
+#ifndef Z_SOLO
+
+ /* utility functions */
+
+/*
+ The following utility functions are implemented on top of the basic
+ stream-oriented functions. To simplify the interface, some default options
+ are assumed (compression level and memory usage, standard memory allocation
+ functions). The source code of these utility functions can be modified if
+ you need special options.
+*/
+
+ZEXTERN int ZEXPORT compress OF((Bytef *dest, uLongf *destLen,
+ const Bytef *source, uLong sourceLen));
+/*
+ Compresses the source buffer into the destination buffer. sourceLen is
+ the byte length of the source buffer. Upon entry, destLen is the total size
+ of the destination buffer, which must be at least the value returned by
+ compressBound(sourceLen). Upon exit, destLen is the actual size of the
+ compressed buffer.
+
+ compress returns Z_OK if success, Z_MEM_ERROR if there was not
+ enough memory, Z_BUF_ERROR if there was not enough room in the output
+ buffer.
+*/
+
+ZEXTERN int ZEXPORT compress2 OF((Bytef *dest, uLongf *destLen,
+ const Bytef *source, uLong sourceLen,
+ int level));
+/*
+ Compresses the source buffer into the destination buffer. The level
+ parameter has the same meaning as in deflateInit. sourceLen is the byte
+ length of the source buffer. Upon entry, destLen is the total size of the
+ destination buffer, which must be at least the value returned by
+ compressBound(sourceLen). Upon exit, destLen is the actual size of the
+ compressed buffer.
+
+ compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough
+ memory, Z_BUF_ERROR if there was not enough room in the output buffer,
+ Z_STREAM_ERROR if the level parameter is invalid.
+*/
+
+ZEXTERN uLong ZEXPORT compressBound OF((uLong sourceLen));
+/*
+ compressBound() returns an upper bound on the compressed size after
+ compress() or compress2() on sourceLen bytes. It would be used before a
+ compress() or compress2() call to allocate the destination buffer.
+*/
+
+ZEXTERN int ZEXPORT uncompress OF((Bytef *dest, uLongf *destLen,
+ const Bytef *source, uLong sourceLen));
+/*
+ Decompresses the source buffer into the destination buffer. sourceLen is
+ the byte length of the source buffer. Upon entry, destLen is the total size
+ of the destination buffer, which must be large enough to hold the entire
+ uncompressed data. (The size of the uncompressed data must have been saved
+ previously by the compressor and transmitted to the decompressor by some
+ mechanism outside the scope of this compression library.) Upon exit, destLen
+ is the actual size of the uncompressed buffer.
+
+ uncompress returns Z_OK if success, Z_MEM_ERROR if there was not
+ enough memory, Z_BUF_ERROR if there was not enough room in the output
+ buffer, or Z_DATA_ERROR if the input data was corrupted or incomplete. In
+ the case where there is not enough room, uncompress() will fill the output
+ buffer with the uncompressed data up to that point.
+*/
+
+ /* gzip file access functions */
+
+/*
+ This library supports reading and writing files in gzip (.gz) format with
+ an interface similar to that of stdio, using the functions that start with
+ "gz". The gzip format is different from the zlib format. gzip is a gzip
+ wrapper, documented in RFC 1952, wrapped around a deflate stream.
+*/
+
+typedef struct gzFile_s *gzFile; /* semi-opaque gzip file descriptor */
+
+/*
+ZEXTERN gzFile ZEXPORT gzopen OF((const char *path, const char *mode));
+
+ Opens a gzip (.gz) file for reading or writing. The mode parameter is as
+ in fopen ("rb" or "wb") but can also include a compression level ("wb9") or
+ a strategy: 'f' for filtered data as in "wb6f", 'h' for Huffman-only
+ compression as in "wb1h", 'R' for run-length encoding as in "wb1R", or 'F'
+ for fixed code compression as in "wb9F". (See the description of
+ deflateInit2 for more information about the strategy parameter.) 'T' will
+ request transparent writing or appending with no compression and not using
+ the gzip format.
+
+ "a" can be used instead of "w" to request that the gzip stream that will
+ be written be appended to the file. "+" will result in an error, since
+ reading and writing to the same gzip file is not supported. The addition of
+ "x" when writing will create the file exclusively, which fails if the file
+ already exists. On systems that support it, the addition of "e" when
+ reading or writing will set the flag to close the file on an execve() call.
+
+ These functions, as well as gzip, will read and decode a sequence of gzip
+ streams in a file. The append function of gzopen() can be used to create
+ such a file. (Also see gzflush() for another way to do this.) When
+ appending, gzopen does not test whether the file begins with a gzip stream,
+ nor does it look for the end of the gzip streams to begin appending. gzopen
+ will simply append a gzip stream to the existing file.
+
+ gzopen can be used to read a file which is not in gzip format; in this
+ case gzread will directly read from the file without decompression. When
+ reading, this will be detected automatically by looking for the magic two-
+ byte gzip header.
+
+ gzopen returns NULL if the file could not be opened, if there was
+ insufficient memory to allocate the gzFile state, or if an invalid mode was
+ specified (an 'r', 'w', or 'a' was not provided, or '+' was provided).
+ errno can be checked to determine if the reason gzopen failed was that the
+ file could not be opened.
+*/
+
+ZEXTERN gzFile ZEXPORT gzdopen OF((int fd, const char *mode));
+/*
+ gzdopen associates a gzFile with the file descriptor fd. File descriptors
+ are obtained from calls like open, dup, creat, pipe or fileno (if the file
+ has been previously opened with fopen). The mode parameter is as in gzopen.
+
+ The next call of gzclose on the returned gzFile will also close the file
+ descriptor fd, just like fclose(fdopen(fd, mode)) closes the file descriptor
+ fd. If you want to keep fd open, use fd = dup(fd_keep); gz = gzdopen(fd,
+ mode);. The duplicated descriptor should be saved to avoid a leak, since
+ gzdopen does not close fd if it fails. If you are using fileno() to get the
+ file descriptor from a FILE *, then you will have to use dup() to avoid
+ double-close()ing the file descriptor. Both gzclose() and fclose() will
+ close the associated file descriptor, so they need to have different file
+ descriptors.
+
+ gzdopen returns NULL if there was insufficient memory to allocate the
+ gzFile state, if an invalid mode was specified (an 'r', 'w', or 'a' was not
+ provided, or '+' was provided), or if fd is -1. The file descriptor is not
+ used until the next gz* read, write, seek, or close operation, so gzdopen
+ will not detect if fd is invalid (unless fd is -1).
+*/
+
+ZEXTERN int ZEXPORT gzbuffer OF((gzFile file, unsigned size));
+/*
+ Set the internal buffer size used by this library's functions. The
+ default buffer size is 8192 bytes. This function must be called after
+ gzopen() or gzdopen(), and before any other calls that read or write the
+ file. The buffer memory allocation is always deferred to the first read or
+ write. Two buffers are allocated, either both of the specified size when
+ writing, or one of the specified size and the other twice that size when
+ reading. A larger buffer size of, for example, 64K or 128K bytes will
+ noticeably increase the speed of decompression (reading).
+
+ The new buffer size also affects the maximum length for gzprintf().
+
+ gzbuffer() returns 0 on success, or -1 on failure, such as being called
+ too late.
+*/
+
+ZEXTERN int ZEXPORT gzsetparams OF((gzFile file, int level, int strategy));
+/*
+ Dynamically update the compression level or strategy. See the description
+ of deflateInit2 for the meaning of these parameters.
+
+ gzsetparams returns Z_OK if success, or Z_STREAM_ERROR if the file was not
+ opened for writing.
+*/
+
+ZEXTERN int ZEXPORT gzread OF((gzFile file, voidp buf, unsigned len));
+/*
+ Reads the given number of uncompressed bytes from the compressed file. If
+ the input file is not in gzip format, gzread copies the given number of
+ bytes into the buffer directly from the file.
+
+ After reaching the end of a gzip stream in the input, gzread will continue
+ to read, looking for another gzip stream. Any number of gzip streams may be
+ concatenated in the input file, and will all be decompressed by gzread().
+ If something other than a gzip stream is encountered after a gzip stream,
+ that remaining trailing garbage is ignored (and no error is returned).
+
+ gzread can be used to read a gzip file that is being concurrently written.
+ Upon reaching the end of the input, gzread will return with the available
+ data. If the error code returned by gzerror is Z_OK or Z_BUF_ERROR, then
+ gzclearerr can be used to clear the end of file indicator in order to permit
+ gzread to be tried again. Z_OK indicates that a gzip stream was completed
+ on the last gzread. Z_BUF_ERROR indicates that the input file ended in the
+ middle of a gzip stream. Note that gzread does not return -1 in the event
+ of an incomplete gzip stream. This error is deferred until gzclose(), which
+ will return Z_BUF_ERROR if the last gzread ended in the middle of a gzip
+ stream. Alternatively, gzerror can be used before gzclose to detect this
+ case.
+
+ gzread returns the number of uncompressed bytes actually read, less than
+ len for end of file, or -1 for error.
+*/
+
+ZEXTERN int ZEXPORT gzwrite OF((gzFile file,
+ voidpc buf, unsigned len));
+/*
+ Writes the given number of uncompressed bytes into the compressed file.
+ gzwrite returns the number of uncompressed bytes written or 0 in case of
+ error.
+*/
+
+ZEXTERN int ZEXPORTVA gzprintf Z_ARG((gzFile file, const char *format, ...));
+/*
+ Converts, formats, and writes the arguments to the compressed file under
+ control of the format string, as in fprintf. gzprintf returns the number of
+ uncompressed bytes actually written, or 0 in case of error. The number of
+ uncompressed bytes written is limited to 8191, or one less than the buffer
+ size given to gzbuffer(). The caller should assure that this limit is not
+ exceeded. If it is exceeded, then gzprintf() will return an error (0) with
+ nothing written. In this case, there may also be a buffer overflow with
+ unpredictable consequences, which is possible only if zlib was compiled with
+ the insecure functions sprintf() or vsprintf() because the secure snprintf()
+ or vsnprintf() functions were not available. This can be determined using
+ zlibCompileFlags().
+*/
+
+ZEXTERN int ZEXPORT gzputs OF((gzFile file, const char *s));
+/*
+ Writes the given null-terminated string to the compressed file, excluding
+ the terminating null character.
+
+ gzputs returns the number of characters written, or -1 in case of error.
+*/
+
+ZEXTERN char * ZEXPORT gzgets OF((gzFile file, char *buf, int len));
+/*
+ Reads bytes from the compressed file until len-1 characters are read, or a
+ newline character is read and transferred to buf, or an end-of-file
+ condition is encountered. If any characters are read or if len == 1, the
+ string is terminated with a null character. If no characters are read due
+ to an end-of-file or len < 1, then the buffer is left untouched.
+
+ gzgets returns buf which is a null-terminated string, or it returns NULL
+ for end-of-file or in case of error. If there was an error, the contents at
+ buf are indeterminate.
+*/
+
+ZEXTERN int ZEXPORT gzputc OF((gzFile file, int c));
+/*
+ Writes c, converted to an unsigned char, into the compressed file. gzputc
+ returns the value that was written, or -1 in case of error.
+*/
+
+ZEXTERN int ZEXPORT gzgetc OF((gzFile file));
+/*
+ Reads one byte from the compressed file. gzgetc returns this byte or -1
+ in case of end of file or error. This is implemented as a macro for speed.
+ As such, it does not do all of the checking the other functions do. I.e.
+ it does not check to see if file is NULL, nor whether the structure file
+ points to has been clobbered or not.
+*/
+
+ZEXTERN int ZEXPORT gzungetc OF((int c, gzFile file));
+/*
+ Push one character back onto the stream to be read as the first character
+ on the next read. At least one character of push-back is allowed.
+ gzungetc() returns the character pushed, or -1 on failure. gzungetc() will
+ fail if c is -1, and may fail if a character has been pushed but not read
+ yet. If gzungetc is used immediately after gzopen or gzdopen, at least the
+ output buffer size of pushed characters is allowed. (See gzbuffer above.)
+ The pushed character will be discarded if the stream is repositioned with
+ gzseek() or gzrewind().
+*/
+
+ZEXTERN int ZEXPORT gzflush OF((gzFile file, int flush));
+/*
+ Flushes all pending output into the compressed file. The parameter flush
+ is as in the deflate() function. The return value is the zlib error number
+ (see function gzerror below). gzflush is only permitted when writing.
+
+ If the flush parameter is Z_FINISH, the remaining data is written and the
+ gzip stream is completed in the output. If gzwrite() is called again, a new
+ gzip stream will be started in the output. gzread() is able to read such
+ concatented gzip streams.
+
+ gzflush should be called only when strictly necessary because it will
+ degrade compression if called too often.
+*/
+
+/*
+ZEXTERN z_off_t ZEXPORT gzseek OF((gzFile file,
+ z_off_t offset, int whence));
+
+ Sets the starting position for the next gzread or gzwrite on the given
+ compressed file. The offset represents a number of bytes in the
+ uncompressed data stream. The whence parameter is defined as in lseek(2);
+ the value SEEK_END is not supported.
+
+ If the file is opened for reading, this function is emulated but can be
+ extremely slow. If the file is opened for writing, only forward seeks are
+ supported; gzseek then compresses a sequence of zeroes up to the new
+ starting position.
+
+ gzseek returns the resulting offset location as measured in bytes from
+ the beginning of the uncompressed stream, or -1 in case of error, in
+ particular if the file is opened for writing and the new starting position
+ would be before the current position.
+*/
+
+ZEXTERN int ZEXPORT gzrewind OF((gzFile file));
+/*
+ Rewinds the given file. This function is supported only for reading.
+
+ gzrewind(file) is equivalent to (int)gzseek(file, 0L, SEEK_SET)
+*/
+
+/*
+ZEXTERN z_off_t ZEXPORT gztell OF((gzFile file));
+
+ Returns the starting position for the next gzread or gzwrite on the given
+ compressed file. This position represents a number of bytes in the
+ uncompressed data stream, and is zero when starting, even if appending or
+ reading a gzip stream from the middle of a file using gzdopen().
+
+ gztell(file) is equivalent to gzseek(file, 0L, SEEK_CUR)
+*/
+
+/*
+ZEXTERN z_off_t ZEXPORT gzoffset OF((gzFile file));
+
+ Returns the current offset in the file being read or written. This offset
+ includes the count of bytes that precede the gzip stream, for example when
+ appending or when using gzdopen() for reading. When reading, the offset
+ does not include as yet unused buffered input. This information can be used
+ for a progress indicator. On error, gzoffset() returns -1.
+*/
+
+ZEXTERN int ZEXPORT gzeof OF((gzFile file));
+/*
+ Returns true (1) if the end-of-file indicator has been set while reading,
+ false (0) otherwise. Note that the end-of-file indicator is set only if the
+ read tried to go past the end of the input, but came up short. Therefore,
+ just like feof(), gzeof() may return false even if there is no more data to
+ read, in the event that the last read request was for the exact number of
+ bytes remaining in the input file. This will happen if the input file size
+ is an exact multiple of the buffer size.
+
+ If gzeof() returns true, then the read functions will return no more data,
+ unless the end-of-file indicator is reset by gzclearerr() and the input file
+ has grown since the previous end of file was detected.
+*/
+
+ZEXTERN int ZEXPORT gzdirect OF((gzFile file));
+/*
+ Returns true (1) if file is being copied directly while reading, or false
+ (0) if file is a gzip stream being decompressed.
+
+ If the input file is empty, gzdirect() will return true, since the input
+ does not contain a gzip stream.
+
+ If gzdirect() is used immediately after gzopen() or gzdopen() it will
+ cause buffers to be allocated to allow reading the file to determine if it
+ is a gzip file. Therefore if gzbuffer() is used, it should be called before
+ gzdirect().
+
+ When writing, gzdirect() returns true (1) if transparent writing was
+ requested ("wT" for the gzopen() mode), or false (0) otherwise. (Note:
+ gzdirect() is not needed when writing. Transparent writing must be
+ explicitly requested, so the application already knows the answer. When
+ linking statically, using gzdirect() will include all of the zlib code for
+ gzip file reading and decompression, which may not be desired.)
+*/
+
+ZEXTERN int ZEXPORT gzclose OF((gzFile file));
+/*
+ Flushes all pending output if necessary, closes the compressed file and
+ deallocates the (de)compression state. Note that once file is closed, you
+ cannot call gzerror with file, since its structures have been deallocated.
+ gzclose must not be called more than once on the same file, just as free
+ must not be called more than once on the same allocation.
+
+ gzclose will return Z_STREAM_ERROR if file is not valid, Z_ERRNO on a
+ file operation error, Z_MEM_ERROR if out of memory, Z_BUF_ERROR if the
+ last read ended in the middle of a gzip stream, or Z_OK on success.
+*/
+
+ZEXTERN int ZEXPORT gzclose_r OF((gzFile file));
+ZEXTERN int ZEXPORT gzclose_w OF((gzFile file));
+/*
+ Same as gzclose(), but gzclose_r() is only for use when reading, and
+ gzclose_w() is only for use when writing or appending. The advantage to
+ using these instead of gzclose() is that they avoid linking in zlib
+ compression or decompression code that is not used when only reading or only
+ writing respectively. If gzclose() is used, then both compression and
+ decompression code will be included the application when linking to a static
+ zlib library.
+*/
+
+ZEXTERN const char * ZEXPORT gzerror OF((gzFile file, int *errnum));
+/*
+ Returns the error message for the last error which occurred on the given
+ compressed file. errnum is set to zlib error number. If an error occurred
+ in the file system and not in the compression library, errnum is set to
+ Z_ERRNO and the application may consult errno to get the exact error code.
+
+ The application must not modify the returned string. Future calls to
+ this function may invalidate the previously returned string. If file is
+ closed, then the string previously returned by gzerror will no longer be
+ available.
+
+ gzerror() should be used to distinguish errors from end-of-file for those
+ functions above that do not distinguish those cases in their return values.
+*/
+
+ZEXTERN void ZEXPORT gzclearerr OF((gzFile file));
+/*
+ Clears the error and end-of-file flags for file. This is analogous to the
+ clearerr() function in stdio. This is useful for continuing to read a gzip
+ file that is being written concurrently.
+*/
+
+#endif /* !Z_SOLO */
+
+ /* checksum functions */
+
+/*
+ These functions are not related to compression but are exported
+ anyway because they might be useful in applications using the compression
+ library.
+*/
+
+ZEXTERN uLong ZEXPORT adler32 OF((uLong adler, const Bytef *buf, uInt len));
+/*
+ Update a running Adler-32 checksum with the bytes buf[0..len-1] and
+ return the updated checksum. If buf is Z_NULL, this function returns the
+ required initial value for the checksum.
+
+ An Adler-32 checksum is almost as reliable as a CRC32 but can be computed
+ much faster.
+
+ Usage example:
+
+ uLong adler = adler32(0L, Z_NULL, 0);
+
+ while (read_buffer(buffer, length) != EOF) {
+ adler = adler32(adler, buffer, length);
+ }
+ if (adler != original_adler) error();
+*/
+
+/*
+ZEXTERN uLong ZEXPORT adler32_combine OF((uLong adler1, uLong adler2,
+ z_off_t len2));
+
+ Combine two Adler-32 checksums into one. For two sequences of bytes, seq1
+ and seq2 with lengths len1 and len2, Adler-32 checksums were calculated for
+ each, adler1 and adler2. adler32_combine() returns the Adler-32 checksum of
+ seq1 and seq2 concatenated, requiring only adler1, adler2, and len2. Note
+ that the z_off_t type (like off_t) is a signed integer. If len2 is
+ negative, the result has no meaning or utility.
+*/
+
+ZEXTERN uLong ZEXPORT crc32 OF((uLong crc, const Bytef *buf, uInt len));
+/*
+ Update a running CRC-32 with the bytes buf[0..len-1] and return the
+ updated CRC-32. If buf is Z_NULL, this function returns the required
+ initial value for the crc. Pre- and post-conditioning (one's complement) is
+ performed within this function so it shouldn't be done by the application.
+
+ Usage example:
+
+ uLong crc = crc32(0L, Z_NULL, 0);
+
+ while (read_buffer(buffer, length) != EOF) {
+ crc = crc32(crc, buffer, length);
+ }
+ if (crc != original_crc) error();
+*/
+
+/*
+ZEXTERN uLong ZEXPORT crc32_combine OF((uLong crc1, uLong crc2, z_off_t len2));
+
+ Combine two CRC-32 check values into one. For two sequences of bytes,
+ seq1 and seq2 with lengths len1 and len2, CRC-32 check values were
+ calculated for each, crc1 and crc2. crc32_combine() returns the CRC-32
+ check value of seq1 and seq2 concatenated, requiring only crc1, crc2, and
+ len2.
+*/
+
+
+ /* various hacks, don't look :) */
+
+/* deflateInit and inflateInit are macros to allow checking the zlib version
+ * and the compiler's view of z_stream:
+ */
+ZEXTERN int ZEXPORT deflateInit_ OF((z_streamp strm, int level,
+ const char *version, int stream_size));
+ZEXTERN int ZEXPORT inflateInit_ OF((z_streamp strm,
+ const char *version, int stream_size));
+ZEXTERN int ZEXPORT deflateInit2_ OF((z_streamp strm, int level, int method,
+ int windowBits, int memLevel,
+ int strategy, const char *version,
+ int stream_size));
+ZEXTERN int ZEXPORT inflateInit2_ OF((z_streamp strm, int windowBits,
+ const char *version, int stream_size));
+ZEXTERN int ZEXPORT inflateBackInit_ OF((z_streamp strm, int windowBits,
+ unsigned char FAR *window,
+ const char *version,
+ int stream_size));
+#define deflateInit(strm, level) \
+ deflateInit_((strm), (level), ZLIB_VERSION, (int)sizeof(z_stream))
+#define inflateInit(strm) \
+ inflateInit_((strm), ZLIB_VERSION, (int)sizeof(z_stream))
+#define deflateInit2(strm, level, method, windowBits, memLevel, strategy) \
+ deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\
+ (strategy), ZLIB_VERSION, (int)sizeof(z_stream))
+#define inflateInit2(strm, windowBits) \
+ inflateInit2_((strm), (windowBits), ZLIB_VERSION, \
+ (int)sizeof(z_stream))
+#define inflateBackInit(strm, windowBits, window) \
+ inflateBackInit_((strm), (windowBits), (window), \
+ ZLIB_VERSION, (int)sizeof(z_stream))
+
+#ifndef Z_SOLO
+
+/* gzgetc() macro and its supporting function and exposed data structure. Note
+ * that the real internal state is much larger than the exposed structure.
+ * This abbreviated structure exposes just enough for the gzgetc() macro. The
+ * user should not mess with these exposed elements, since their names or
+ * behavior could change in the future, perhaps even capriciously. They can
+ * only be used by the gzgetc() macro. You have been warned.
+ */
+struct gzFile_s {
+ unsigned have;
+ unsigned char *next;
+ z_off64_t pos;
+};
+ZEXTERN int ZEXPORT gzgetc_ OF((gzFile file)); /* backward compatibility */
+#ifdef Z_PREFIX_SET
+# undef z_gzgetc
+# define z_gzgetc(g) \
+ ((g)->have ? ((g)->have--, (g)->pos++, *((g)->next)++) : gzgetc(g))
+#else
+# define gzgetc(g) \
+ ((g)->have ? ((g)->have--, (g)->pos++, *((g)->next)++) : gzgetc(g))
+#endif
+
+/* provide 64-bit offset functions if _LARGEFILE64_SOURCE defined, and/or
+ * change the regular functions to 64 bits if _FILE_OFFSET_BITS is 64 (if
+ * both are true, the application gets the *64 functions, and the regular
+ * functions are changed to 64 bits) -- in case these are set on systems
+ * without large file support, _LFS64_LARGEFILE must also be true
+ */
+#ifdef Z_LARGE64
+ ZEXTERN gzFile ZEXPORT gzopen64 OF((const char *, const char *));
+ ZEXTERN z_off64_t ZEXPORT gzseek64 OF((gzFile, z_off64_t, int));
+ ZEXTERN z_off64_t ZEXPORT gztell64 OF((gzFile));
+ ZEXTERN z_off64_t ZEXPORT gzoffset64 OF((gzFile));
+ ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off64_t));
+ ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off64_t));
+#endif
+
+#if !defined(ZLIB_INTERNAL) && defined(Z_WANT64)
+# ifdef Z_PREFIX_SET
+# define z_gzopen z_gzopen64
+# define z_gzseek z_gzseek64
+# define z_gztell z_gztell64
+# define z_gzoffset z_gzoffset64
+# define z_adler32_combine z_adler32_combine64
+# define z_crc32_combine z_crc32_combine64
+# else
+# define gzopen gzopen64
+# define gzseek gzseek64
+# define gztell gztell64
+# define gzoffset gzoffset64
+# define adler32_combine adler32_combine64
+# define crc32_combine crc32_combine64
+# endif
+# ifndef Z_LARGE64
+ ZEXTERN gzFile ZEXPORT gzopen64 OF((const char *, const char *));
+ ZEXTERN z_off_t ZEXPORT gzseek64 OF((gzFile, z_off_t, int));
+ ZEXTERN z_off_t ZEXPORT gztell64 OF((gzFile));
+ ZEXTERN z_off_t ZEXPORT gzoffset64 OF((gzFile));
+ ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off_t));
+ ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off_t));
+# endif
+#else
+ ZEXTERN gzFile ZEXPORT gzopen OF((const char *, const char *));
+ ZEXTERN z_off_t ZEXPORT gzseek OF((gzFile, z_off_t, int));
+ ZEXTERN z_off_t ZEXPORT gztell OF((gzFile));
+ ZEXTERN z_off_t ZEXPORT gzoffset OF((gzFile));
+ ZEXTERN uLong ZEXPORT adler32_combine OF((uLong, uLong, z_off_t));
+ ZEXTERN uLong ZEXPORT crc32_combine OF((uLong, uLong, z_off_t));
+#endif
+
+#else /* Z_SOLO */
+
+ ZEXTERN uLong ZEXPORT adler32_combine OF((uLong, uLong, z_off_t));
+ ZEXTERN uLong ZEXPORT crc32_combine OF((uLong, uLong, z_off_t));
+
+#endif /* !Z_SOLO */
+
+/* hack for buggy compilers */
+#if !defined(ZUTIL_H) && !defined(NO_DUMMY_DECL)
+ struct internal_state {int dummy;};
+#endif
+
+/* undocumented functions */
+ZEXTERN const char * ZEXPORT zError OF((int));
+ZEXTERN int ZEXPORT inflateSyncPoint OF((z_streamp));
+ZEXTERN const z_crc_t FAR * ZEXPORT get_crc_table OF((void));
+ZEXTERN int ZEXPORT inflateUndermine OF((z_streamp, int));
+ZEXTERN int ZEXPORT inflateResetKeep OF((z_streamp));
+ZEXTERN int ZEXPORT deflateResetKeep OF((z_streamp));
+#if defined(_WIN32) && !defined(Z_SOLO)
+ZEXTERN gzFile ZEXPORT gzopen_w OF((const wchar_t *path,
+ const char *mode));
+#endif
+#if defined(STDC) || defined(Z_HAVE_STDARG_H)
+# ifndef Z_SOLO
+ZEXTERN int ZEXPORTVA gzvprintf Z_ARG((gzFile file,
+ const char *format,
+ va_list va));
+# endif
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* ZLIB_H */
diff --git a/frontend/cspace.c b/frontend/cspace.c
index 33a981d..55d4ac6 100644
--- a/frontend/cspace.c
+++ b/frontend/cspace.c
@@ -34,24 +34,46 @@ void bgr555_to_rgb565(void *dst_, const void *src_, int bytes)
#endif
+#ifdef __arm64__
+
+void bgr888_to_rgb565(void *dst_, const void *src_, int bytes)
+{
+ const unsigned char *src = src_;
+ unsigned int *dst = dst_;
+ unsigned int r1, g1, b1, r2, g2, b2;
+
+ for (; bytes >= 6; bytes -= 6, src += 6, dst++) {
+ r1 = src[0] & 0xf8;
+ g1 = src[1] & 0xfc;
+ b1 = src[2] & 0xf8;
+ r2 = src[3] & 0xf8;
+ g2 = src[4] & 0xfc;
+ b2 = src[5] & 0xf8;
+ *dst = (r2 << 24) | (g2 << 19) | (b2 << 13) |
+ (r1 << 8) | (g1 << 3) | (b1 >> 3);
+ }
+}
+
+#endif
+
#ifndef __ARM_NEON__
void bgr888_to_rgb565(void *dst_, const void *src_, int bytes)
{
- const unsigned char *src = src_;
- unsigned int *dst = dst_;
- unsigned int r1, g1, b1, r2, g2, b2;
-
- for (; bytes >= 6; bytes -= 6, src += 6, dst++) {
- r1 = src[0] & 0xf8;
- g1 = src[1] & 0xfc;
- b1 = src[2] & 0xf8;
- r2 = src[3] & 0xf8;
- g2 = src[4] & 0xfc;
- b2 = src[5] & 0xf8;
- *dst = (r2 << 24) | (g2 << 19) | (b2 << 13) |
- (r1 << 8) | (g1 << 3) | (b1 >> 3);
- }
+ const unsigned char *src = src_;
+ unsigned int *dst = dst_;
+ unsigned int r1, g1, b1, r2, g2, b2;
+
+ for (; bytes >= 6; bytes -= 6, src += 6, dst++) {
+ r1 = src[0] & 0xf8;
+ g1 = src[1] & 0xfc;
+ b1 = src[2] & 0xf8;
+ r2 = src[3] & 0xf8;
+ g2 = src[4] & 0xfc;
+ b2 = src[5] & 0xf8;
+ *dst = (r2 << 24) | (g2 << 19) | (b2 << 13) |
+ (r1 << 8) | (g1 << 3) | (b1 >> 3);
+ }
}
// TODO?
diff --git a/frontend/libpicofe b/frontend/libpicofe
deleted file mode 160000
-Subproject 21604a047941b8fe81d381ede0371c75da964af
diff --git a/frontend/libretro.c b/frontend/libretro.c
index 940ff05..992da60 100644
--- a/frontend/libretro.c
+++ b/frontend/libretro.c
@@ -22,47 +22,115 @@
#include "../libpcsxcore/cdrom.h"
#include "../libpcsxcore/cdriso.h"
#include "../libpcsxcore/cheat.h"
+#include "../libpcsxcore/r3000a.h"
#include "../plugins/dfsound/out.h"
#include "../plugins/dfsound/spu_config.h"
#include "../plugins/dfinput/externals.h"
#include "cspace.h"
#include "main.h"
+#include "menu.h"
#include "plugin.h"
#include "plugin_lib.h"
#include "arm_features.h"
#include "revision.h"
#include "libretro.h"
+#ifdef _3DS
+#include "3ds/3ds_utils.h"
+#endif
+
+#define PORTS_NUMBER 8
+
+#ifndef MIN
+#define MIN(a, b) ((a) < (b) ? (a) : (b))
+#endif
+
+#ifndef MAX
+#define MAX(a, b) ((a) > (b) ? (a) : (b))
+#endif
+
+#define ISHEXDEC ((buf[cursor]>='0') && (buf[cursor]<='9')) || ((buf[cursor]>='a') && (buf[cursor]<='f')) || ((buf[cursor]>='A') && (buf[cursor]<='F'))
+
+#define INTERNAL_FPS_SAMPLE_PERIOD 64
+
+//hack to prevent retroarch freezing when reseting in the menu but not while running with the hot key
+static int rebootemu = 0;
+
static retro_video_refresh_t video_cb;
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 retro_set_rumble_state_t rumble_cb;
+static struct retro_log_callback logging;
+static retro_log_printf_t log_cb;
static void *vout_buf;
+static void * vout_buf_ptr;
static int vout_width, vout_height;
static int vout_doffs_old, vout_fb_dirty;
static bool vout_can_dupe;
static bool duping_enable;
+static bool found_bios;
+static bool display_internal_fps = false;
+static unsigned frame_count = 0;
+static bool libretro_supports_bitmasks = false;
+
+static unsigned previous_width = 0;
+static unsigned previous_height = 0;
static int plugins_opened;
static int is_pal_mode;
/* memory card data */
extern char Mcd1Data[MCD_SIZE];
+extern char Mcd2Data[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 };
-int in_keystate;
+int in_type[8] = { PSE_PAD_TYPE_NONE, PSE_PAD_TYPE_NONE,
+ PSE_PAD_TYPE_NONE, PSE_PAD_TYPE_NONE,
+ PSE_PAD_TYPE_NONE, PSE_PAD_TYPE_NONE,
+ PSE_PAD_TYPE_NONE, PSE_PAD_TYPE_NONE };
+int in_analog_left[8][2] = {{ 127, 127 },{ 127, 127 },{ 127, 127 },{ 127, 127 },{ 127, 127 },{ 127, 127 },{ 127, 127 },{ 127, 127 }};
+int in_analog_right[8][2] = {{ 127, 127 },{ 127, 127 },{ 127, 127 },{ 127, 127 },{ 127, 127 },{ 127, 127 },{ 127, 127 },{ 127, 127 }};
+unsigned short in_keystate[PORTS_NUMBER];
+int multitap1 = 0;
+int multitap2 = 0;
int in_enable_vibration = 1;
+// NegCon adjustment parameters
+// > The NegCon 'twist' action is somewhat awkward when mapped
+// to a standard analog stick -> user should be able to tweak
+// response/deadzone for comfort
+// > When response is linear, 'additional' deadzone (set here)
+// may be left at zero, since this is normally handled via in-game
+// options menus
+// > When response is non-linear, deadzone should be set to match the
+// controller being used (otherwise precision may be lost)
+// > negcon_linearity:
+// - 1: Response is linear - recommended when using racing wheel
+// peripherals, not recommended for standard gamepads
+// - 2: Response is quadratic - optimal setting for gamepads
+// - 3: Response is cubic - enables precise fine control, but
+// difficult to use...
+#define NEGCON_RANGE 0x7FFF
+static int negcon_deadzone = 0;
+static int negcon_linearity = 1;
+
/* PSX max resolution is 640x512, but with enhancement it's 1024x512 */
#define VOUT_MAX_WIDTH 1024
#define VOUT_MAX_HEIGHT 512
+//Dummy functions
+bool retro_load_game_special(unsigned game_type, const struct retro_game_info *info, size_t num_info){return false;}
+void retro_unload_game(void){}
+static int vout_open(void){return 0;}
+static void vout_close(void){}
+static int snd_init(void){return 0;}
+static void snd_finish(void){}
+static int snd_busy(void){return 0;}
+
static void init_memcard(char *mcd_data)
{
unsigned off = 0;
@@ -96,15 +164,38 @@ static void init_memcard(char *mcd_data)
}
}
-static int vout_open(void)
+static void set_vout_fb()
{
- return 0;
+ struct retro_framebuffer fb = {0};
+
+ fb.width = vout_width;
+ fb.height = vout_height;
+ fb.access_flags = RETRO_MEMORY_ACCESS_WRITE;
+
+ if (environ_cb(RETRO_ENVIRONMENT_GET_CURRENT_SOFTWARE_FRAMEBUFFER, &fb) && fb.format == RETRO_PIXEL_FORMAT_RGB565)
+ vout_buf_ptr = (uint16_t*)fb.data;
+ else
+ vout_buf_ptr = vout_buf;
}
static void vout_set_mode(int w, int h, int raw_w, int raw_h, int bpp)
{
- vout_width = w;
- vout_height = h;
+ vout_width = w;
+ vout_height = h;
+
+ if (previous_width != vout_width || previous_height != vout_height)
+ {
+ previous_width = vout_width;
+ previous_height = vout_height;
+
+ SysPrintf("setting mode width: %d height %d\n", vout_width, vout_height);
+
+ struct retro_system_av_info info;
+ retro_get_system_av_info(&info);
+ environ_cb(RETRO_ENVIRONMENT_SET_GEOMETRY, &info.geometry);
+ }
+
+ set_vout_fb();
}
#ifndef FRONTEND_SUPPORTS_RGB565
@@ -121,14 +212,14 @@ static void convert(void *buf, size_t bytes)
static void vout_flip(const void *vram, int stride, int bgr24, int w, int h)
{
- unsigned short *dest = vout_buf;
+ unsigned short *dest = vout_buf_ptr;
const unsigned short *src = vram;
int dstride = vout_width, h1 = h;
int doffs;
if (vram == NULL) {
// blanking
- memset(vout_buf, 0, dstride * h * 2);
+ memset(vout_buf_ptr, 0, dstride * h * 2);
goto out;
}
@@ -136,7 +227,7 @@ static void vout_flip(const void *vram, int stride, int bgr24, int w, int h)
doffs += (dstride - w) / 2 & ~1;
if (doffs != vout_doffs_old) {
// clear borders
- memset(vout_buf, 0, dstride * h * 2);
+ memset(vout_buf_ptr, 0, dstride * h * 2);
vout_doffs_old = doffs;
}
dest += doffs;
@@ -159,15 +250,172 @@ static void vout_flip(const void *vram, int stride, int bgr24, int w, int h)
out:
#ifndef FRONTEND_SUPPORTS_RGB565
- convert(vout_buf, vout_width * vout_height * 2);
+ convert(vout_buf_ptr, vout_width * vout_height * 2);
#endif
vout_fb_dirty = 1;
pl_rearmed_cbs.flip_cnt++;
}
-static void vout_close(void)
+#ifdef _3DS
+typedef struct
+{
+ void* buffer;
+ uint32_t target_map;
+ size_t size;
+ enum psxMapTag tag;
+}psx_map_t;
+
+psx_map_t custom_psx_maps[] = {
+ {NULL, 0x13000000, 0x210000, MAP_TAG_RAM}, // 0x80000000
+ {NULL, 0x12800000, 0x010000, MAP_TAG_OTHER}, // 0x1f800000
+ {NULL, 0x12c00000, 0x080000, MAP_TAG_OTHER}, // 0x1fc00000
+ {NULL, 0x11000000, 0x800000, MAP_TAG_LUTS}, // 0x08000000
+ {NULL, 0x12000000, 0x200000, MAP_TAG_VRAM}, // 0x00000000
+};
+
+void* pl_3ds_mmap(unsigned long addr, size_t size, int is_fixed,
+ enum psxMapTag tag)
+{
+ (void)is_fixed;
+ (void)addr;
+
+ if (__ctr_svchax)
+ {
+ psx_map_t* custom_map = custom_psx_maps;
+
+ for (; custom_map->size; custom_map++)
+ {
+ if ((custom_map->size == size) && (custom_map->tag == tag))
+ {
+ uint32_t ptr_aligned, tmp;
+
+ custom_map->buffer = malloc(size + 0x1000);
+ ptr_aligned = (((u32)custom_map->buffer) + 0xFFF) & ~0xFFF;
+
+ if(svcControlMemory(&tmp, (void*)custom_map->target_map, (void*)ptr_aligned, size, MEMOP_MAP, 0x3) < 0)
+ {
+ SysPrintf("could not map memory @0x%08X\n", custom_map->target_map);
+ exit(1);
+ }
+
+ return (void*)custom_map->target_map;
+ }
+ }
+ }
+
+ return malloc(size);
+}
+
+void pl_3ds_munmap(void *ptr, size_t size, enum psxMapTag tag)
+{
+ (void)tag;
+
+ if (__ctr_svchax)
+ {
+ psx_map_t* custom_map = custom_psx_maps;
+
+ for (; custom_map->size; custom_map++)
+ {
+ if ((custom_map->target_map == (uint32_t)ptr))
+ {
+ uint32_t ptr_aligned, tmp;
+
+ ptr_aligned = (((u32)custom_map->buffer) + 0xFFF) & ~0xFFF;
+
+ svcControlMemory(&tmp, (void*)custom_map->target_map, (void*)ptr_aligned, size, MEMOP_UNMAP, 0x3);
+
+ free(custom_map->buffer);
+ custom_map->buffer = NULL;
+ return;
+ }
+ }
+ }
+
+ free(ptr);
+}
+#endif
+
+#ifdef VITA
+typedef struct
+{
+ void* buffer;
+ uint32_t target_map;
+ size_t size;
+ enum psxMapTag tag;
+}psx_map_t;
+
+void* addr = NULL;
+
+psx_map_t custom_psx_maps[] = {
+ {NULL, NULL, 0x210000, MAP_TAG_RAM}, // 0x80000000
+ {NULL, NULL, 0x010000, MAP_TAG_OTHER}, // 0x1f800000
+ {NULL, NULL, 0x080000, MAP_TAG_OTHER}, // 0x1fc00000
+ {NULL, NULL, 0x800000, MAP_TAG_LUTS}, // 0x08000000
+ {NULL, NULL, 0x200000, MAP_TAG_VRAM}, // 0x00000000
+};
+
+int init_vita_mmap(){
+ int n;
+ void * tmpaddr;
+ addr = malloc(64*1024*1024);
+ if(addr==NULL)
+ return -1;
+ tmpaddr = ((u32)(addr+0xFFFFFF))&~0xFFFFFF;
+ custom_psx_maps[0].buffer=tmpaddr+0x2000000;
+ custom_psx_maps[1].buffer=tmpaddr+0x1800000;
+ custom_psx_maps[2].buffer=tmpaddr+0x1c00000;
+ custom_psx_maps[3].buffer=tmpaddr+0x0000000;
+ custom_psx_maps[4].buffer=tmpaddr+0x1000000;
+#if 0
+ for(n = 0; n < 5; n++){
+ sceClibPrintf("addr reserved %x\n",custom_psx_maps[n].buffer);
+ }
+#endif
+ return 0;
+}
+
+void deinit_vita_mmap(){
+ free(addr);
+}
+
+void* pl_vita_mmap(unsigned long addr, size_t size, int is_fixed,
+ enum psxMapTag tag)
{
+ (void)is_fixed;
+ (void)addr;
+
+
+ psx_map_t* custom_map = custom_psx_maps;
+
+ for (; custom_map->size; custom_map++)
+ {
+ if ((custom_map->size == size) && (custom_map->tag == tag))
+ {
+ return custom_map->buffer;
+ }
+ }
+
+
+ return malloc(size);
+}
+
+void pl_vita_munmap(void *ptr, size_t size, enum psxMapTag tag)
+{
+ (void)tag;
+
+ psx_map_t* custom_map = custom_psx_maps;
+
+ for (; custom_map->size; custom_map++)
+ {
+ if ((custom_map->buffer == ptr))
+ {
+ return;
+ }
+ }
+
+ free(ptr);
}
+#endif
static void *pl_mmap(unsigned int size)
{
@@ -204,8 +452,14 @@ void pl_timing_prepare(int is_pal)
void plat_trigger_vibrate(int pad, int low, int high)
{
- rumble.set_rumble_state(pad, RETRO_RUMBLE_STRONG, high << 8);
- rumble.set_rumble_state(pad, RETRO_RUMBLE_WEAK, low ? 0xffff : 0x0);
+ if (!rumble_cb)
+ return;
+
+ if (in_enable_vibration)
+ {
+ rumble_cb(pad, RETRO_RUMBLE_STRONG, high << 8);
+ rumble_cb(pad, RETRO_RUMBLE_WEAK, low ? 0xffff : 0x0);
+ }
}
void pl_update_gun(int *xn, int *yn, int *xres, int *yres, int *in)
@@ -213,20 +467,6 @@ void pl_update_gun(int *xn, int *yn, int *xres, int *yres, int *in)
}
/* sound calls */
-static int snd_init(void)
-{
- return 0;
-}
-
-static void snd_finish(void)
-{
-}
-
-static int snd_busy(void)
-{
- return 0;
-}
-
static void snd_feed(void *buf, int bytes)
{
if (audio_batch_cb != NULL)
@@ -247,23 +487,60 @@ void retro_set_environment(retro_environment_t cb)
{
static const struct retro_variable vars[] = {
{ "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" },
+ { "pcsx_rearmed_bios", "Use BIOS; auto|HLE" },
+ { "pcsx_rearmed_region", "Region; auto|NTSC|PAL" },
+ { "pcsx_rearmed_memcard2", "Enable second memory card; disabled|enabled" },
+ { "pcsx_rearmed_pad1type", "Pad 1 Type; standard|analog|dualshock|negcon|none" },
+ { "pcsx_rearmed_pad2type", "Pad 2 Type; standard|analog|dualshock|negcon|none" },
+ { "pcsx_rearmed_pad3type", "Pad 3 Type; none|standard|analog|dualshock|negcon" },
+ { "pcsx_rearmed_pad4type", "Pad 4 Type; none|standard|analog|dualshock|negcon" },
+ { "pcsx_rearmed_pad5type", "Pad 5 Type; none|standard|analog|dualshock|negcon" },
+ { "pcsx_rearmed_pad6type", "Pad 6 Type; none|standard|analog|dualshock|negcon" },
+ { "pcsx_rearmed_pad7type", "Pad 7 Type; none|standard|analog|dualshock|negcon" },
+ { "pcsx_rearmed_pad8type", "Pad 8 Type; none|standard|analog|dualshock|negcon" },
+ { "pcsx_rearmed_multitap1", "Multitap 1; auto|disabled|enabled" },
+ { "pcsx_rearmed_multitap2", "Multitap 2; auto|disabled|enabled" },
+ { "pcsx_rearmed_negcon_deadzone", "NegCon Twist Deadzone (percent); 0|5|10|15|20|25|30" },
+ { "pcsx_rearmed_negcon_response", "NegCon Twist Response; linear|quadratic|cubic" },
+ { "pcsx_rearmed_vibration", "Enable Vibration; enabled|disabled" },
+ { "pcsx_rearmed_dithering", "Enable Dithering; enabled|disabled" },
#ifndef DRC_DISABLE
{ "pcsx_rearmed_drc", "Dynamic recompiler; enabled|disabled" },
+#ifdef HAVE_PRE_ARMV7
+ { "pcsx_rearmed_psxclock", "PSX cpu clock (default 50); 50|51|52|53|54|55|5657|58|59|60|61|62|63|64|65|66|67|68|69|70|71|72|73|74|75|76|77|78|79|80|81|82|83|84|85|86|87|88|89|90|91|92|93|94|95|96|97|98|99|100|30|31|32|33|34|35|36|37|38|39|40|41|42|43|44|45|46|47|48|49" },
+#else
+ { "pcsx_rearmed_psxclock", "PSX cpu clock (default 57); 57|58|59|60|61|62|63|64|65|66|67|68|69|70|71|72|73|74|75|76|77|78|79|80|81|82|83|84|85|86|87|88|89|90|91|92|93|94|95|96|97|98|99|100|30|31|32|33|34|35|36|37|38|39|40|41|42|43|44|45|46|47|48|49|50|51|52|53|54|55|56" },
+#endif
#endif
#ifdef __ARM_NEON__
{ "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" },
- { "pcsx_rearmed_spu_reverb", "Sound: Reverb; on|off" },
+ { "pcsx_rearmed_duping_enable", "Frame duping; enabled|disabled" },
+ { "pcsx_rearmed_display_internal_fps", "Display Internal FPS; disabled|enabled" },
+ { "pcsx_rearmed_show_bios_bootlogo", "Show Bios Bootlogo(Breaks some games); disabled|enabled" },
+ { "pcsx_rearmed_spu_reverb", "Sound: Reverb; enabled|disabled" },
{ "pcsx_rearmed_spu_interpolation", "Sound: Interpolation; simple|gaussian|cubic|off" },
- { NULL, NULL },
+ { "pcsx_rearmed_idiablofix", "Diablo Music Fix; disabled|enabled" },
+ { "pcsx_rearmed_pe2_fix", "Parasite Eve 2/Vandal Hearts 1/2 Fix; disabled|enabled" },
+ { "pcsx_rearmed_inuyasha_fix", "InuYasha Sengoku Battle Fix; disabled|enabled" },
+
+ /* Advance options */
+ { "pcsx_rearmed_noxadecoding", "XA Decoding; enabled|disabled" },
+ { "pcsx_rearmed_nocdaudio", "CD Audio; enabled|disabled" },
+#ifndef DRC_DISABLE
+ { "pcsx_rearmed_nosmccheck", "(Speed Hack) Disable SMC Checks; disabled|enabled" },
+ { "pcsx_rearmed_gteregsunneeded", "(Speed Hack) Assume GTE Regs Unneeded; disabled|enabled" },
+ { "pcsx_rearmed_nogteflags", "(Speed Hack) Disable GTE Flags; disabled|enabled" },
+#endif
+
+ { NULL, NULL }
};
+ if (cb(RETRO_ENVIRONMENT_GET_LOG_INTERFACE, &logging))
+ log_cb = logging.log;
+
environ_cb = cb;
cb(RETRO_ENVIRONMENT_SET_VARIABLES, (void*)vars);
@@ -280,34 +557,195 @@ unsigned retro_api_version(void)
return RETRO_API_VERSION;
}
+static int controller_port_variable(unsigned port, struct retro_variable *var)
+{
+ if (port >= PORTS_NUMBER)
+ return 0;
+
+ if (!environ_cb)
+ return 0;
+
+ var->value = NULL;
+ switch (port) {
+ case 0:
+ var->key = "pcsx_rearmed_pad1type";
+ break;
+ case 1:
+ var->key = "pcsx_rearmed_pad2type";
+ break;
+ case 2:
+ var->key = "pcsx_rearmed_pad3type";
+ break;
+ case 3:
+ var->key = "pcsx_rearmed_pad4type";
+ break;
+ case 4:
+ var->key = "pcsx_rearmed_pad5type";
+ break;
+ case 5:
+ var->key = "pcsx_rearmed_pad6type";
+ break;
+ case 6:
+ var->key = "pcsx_rearmed_pad7type";
+ break;
+ case 7:
+ var->key = "pcsx_rearmed_pad8type";
+ break;
+ }
+
+ return environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, var) || var->value;
+}
+
+static void update_controller_port_variable(unsigned port)
+{
+ if (port >= PORTS_NUMBER)
+ return;
+
+ struct retro_variable var;
+
+ if (controller_port_variable(port, &var))
+ {
+ if (strcmp(var.value, "standard") == 0)
+ in_type[port] = PSE_PAD_TYPE_STANDARD;
+ else if (strcmp(var.value, "analog") == 0)
+ in_type[port] = PSE_PAD_TYPE_ANALOGJOY;
+ else if (strcmp(var.value, "dualshock") == 0)
+ in_type[port] = PSE_PAD_TYPE_ANALOGPAD;
+ else if (strcmp(var.value, "negcon") == 0)
+ in_type[port] = PSE_PAD_TYPE_NEGCON;
+ else if (strcmp(var.value, "none") == 0)
+ in_type[port] = PSE_PAD_TYPE_NONE;
+ // else 'default' case, do nothing
+ }
+}
+
+static void update_controller_port_device(unsigned port, unsigned device)
+{
+ if (port >= PORTS_NUMBER)
+ return;
+
+ struct retro_variable var;
+
+ if (!controller_port_variable(port, &var))
+ return;
+
+ if (strcmp(var.value, "default") != 0)
+ return;
+
+ switch (device)
+ {
+ case RETRO_DEVICE_JOYPAD:
+ in_type[port] = PSE_PAD_TYPE_STANDARD;
+ break;
+ case RETRO_DEVICE_ANALOG:
+ in_type[port] = PSE_PAD_TYPE_ANALOGPAD;
+ break;
+ case RETRO_DEVICE_MOUSE:
+ in_type[port] = PSE_PAD_TYPE_MOUSE;
+ break;
+ case RETRO_DEVICE_LIGHTGUN:
+ in_type[port] = PSE_PAD_TYPE_GUN;
+ break;
+ case RETRO_DEVICE_NONE:
+ default:
+ in_type[port] = PSE_PAD_TYPE_NONE;
+ }
+}
+
+static void update_multitap()
+{
+ struct retro_variable var;
+ int auto_case, port;
+
+ var.value = NULL;
+ var.key = "pcsx_rearmed_multitap1";
+ auto_case = 0;
+ if (environ_cb && (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) || var.value))
+ {
+ if (strcmp(var.value, "enabled") == 0)
+ multitap1 = 1;
+ else if (strcmp(var.value, "disabled") == 0)
+ multitap1 = 0;
+ else // 'auto' case
+ auto_case = 1;
+ }
+ else
+ auto_case = 1;
+
+ if (auto_case)
+ {
+ // If a gamepad is plugged after port 2, we need a first multitap.
+ multitap1 = 0;
+ for (port = 2; port < PORTS_NUMBER; port++)
+ multitap1 |= in_type[port] != PSE_PAD_TYPE_NONE;
+ }
+
+ var.value = NULL;
+ var.key = "pcsx_rearmed_multitap2";
+ auto_case = 0;
+ if (environ_cb && (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) || var.value))
+ {
+ if (strcmp(var.value, "enabled") == 0)
+ multitap2 = 1;
+ else if (strcmp(var.value, "disabled") == 0)
+ multitap2 = 0;
+ else // 'auto' case
+ auto_case = 1;
+ }
+ else
+ auto_case = 1;
+
+ if (auto_case)
+ {
+ // If a gamepad is plugged after port 4, we need a second multitap.
+ multitap2 = 0;
+ for (port = 4; port < PORTS_NUMBER; port++)
+ multitap2 |= in_type[port] != PSE_PAD_TYPE_NONE;
+ }
+}
+
void retro_set_controller_port_device(unsigned port, unsigned device)
{
+ SysPrintf("port %u device %u",port,device);
+
+ if (port >= PORTS_NUMBER)
+ return;
+
+ update_controller_port_device(port, device);
+ update_multitap();
}
void retro_get_system_info(struct retro_system_info *info)
{
memset(info, 0, sizeof(*info));
info->library_name = "PCSX-ReARMed";
- info->library_version = "r22";
- info->valid_extensions = "bin|cue|img|mdf|pbp|toc|cbn|m3u";
+#ifndef GIT_VERSION
+#define GIT_VERSION ""
+#endif
+ info->library_version = "r22" GIT_VERSION;
+ info->valid_extensions = "bin|cue|img|mdf|pbp|toc|cbn|m3u|chd";
info->need_fullpath = true;
}
void retro_get_system_av_info(struct retro_system_av_info *info)
{
+
+ unsigned geom_height = vout_height > 0 ? vout_height : 240;
+ unsigned geom_width = vout_width > 0 ? vout_width : 320;
+
memset(info, 0, sizeof(*info));
info->timing.fps = is_pal_mode ? 50 : 60;
info->timing.sample_rate = 44100;
- info->geometry.base_width = 320;
- info->geometry.base_height = 240;
+ info->geometry.base_width = geom_width;
+ info->geometry.base_height = geom_height;
info->geometry.max_width = VOUT_MAX_WIDTH;
info->geometry.max_height = VOUT_MAX_HEIGHT;
info->geometry.aspect_ratio = 4.0 / 3.0;
}
/* savestates */
-size_t retro_serialize_size(void)
-{
+size_t retro_serialize_size(void)
+{
// it's currently 4380651-4397047 bytes,
// but have some reserved for future
return 0x440000;
@@ -393,7 +831,7 @@ static void save_close(void *file)
}
bool retro_serialize(void *data, size_t size)
-{
+{
int ret = SaveState(data);
return ret == 0 ? true : false;
}
@@ -419,6 +857,21 @@ void retro_cheat_set(unsigned index, bool enabled, const char *code)
strncpy(buf, code, sizeof(buf));
buf[sizeof(buf) - 1] = 0;
+ //Prepare buffered cheat for PCSX's AddCheat fucntion.
+ int cursor=0;
+ int nonhexdec=0;
+ while (buf[cursor]){
+ if (!(ISHEXDEC)){
+ if (++nonhexdec%2){
+ buf[cursor]=' ';
+ } else {
+ buf[cursor]='\n';
+ }
+ }
+ cursor++;
+ }
+
+
if (index < NumCheats)
ret = EditCheat(index, "", buf);
else
@@ -557,6 +1010,10 @@ static struct retro_disk_control_callback disk_control = {
#define SLASH '/'
#endif
+#ifndef PATH_MAX
+#define PATH_MAX 4096
+#endif
+
static char base_dir[PATH_MAX];
static bool read_m3u(const char *file)
@@ -761,7 +1218,7 @@ bool retro_load_game(const struct retro_game_info *info)
{ 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" },
+ { 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" },
@@ -782,7 +1239,7 @@ bool retro_load_game(const struct retro_game_info *info)
{ 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" },
+ { 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" },
@@ -803,7 +1260,7 @@ bool retro_load_game(const struct retro_game_info *info)
{ 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" },
+ { 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" },
@@ -812,6 +1269,8 @@ bool retro_load_game(const struct retro_game_info *info)
{ 0 },
};
+ frame_count = 0;
+
environ_cb(RETRO_ENVIRONMENT_SET_INPUT_DESCRIPTORS, desc);
#ifdef FRONTEND_SUPPORTS_RGB565
@@ -844,7 +1303,7 @@ bool retro_load_game(const struct retro_game_info *info)
if (is_m3u) {
if (!read_m3u(info->path)) {
- SysPrintf("failed to read m3u file\n");
+ log_cb(RETRO_LOG_INFO, "failed to read m3u file\n");
return false;
}
} else {
@@ -856,7 +1315,7 @@ bool retro_load_game(const struct retro_game_info *info)
/* have to reload after set_cd_image for correct cdr plugin */
if (LoadPlugins() == -1) {
- SysPrintf("failed to load plugins\n");
+ log_cb(RETRO_LOG_INFO, "failed to load plugins\n");
return false;
}
@@ -864,23 +1323,22 @@ bool retro_load_game(const struct retro_game_info *info)
NetOpened = 0;
if (OpenPlugins() == -1) {
- SysPrintf("failed to open plugins\n");
+ log_cb(RETRO_LOG_INFO, "failed to open plugins\n");
return false;
}
plugin_call_rearmed_cbs();
dfinput_activate();
- Config.PsxAuto = 1;
if (CheckCdrom() == -1) {
- SysPrintf("unsupported/invalid CD image: %s\n", info->path);
+ log_cb(RETRO_LOG_INFO, "unsupported/invalid CD image: %s\n", info->path);
return false;
}
SysReset();
if (LoadCdrom() == -1) {
- SysPrintf("could not load CD-ROM!\n");
+ log_cb(RETRO_LOG_INFO, "could not load CD\n");
return false;
}
emu_on_new_cd(0);
@@ -897,15 +1355,6 @@ bool retro_load_game(const struct retro_game_info *info)
return true;
}
-bool retro_load_game_special(unsigned game_type, const struct retro_game_info *info, size_t num_info)
-{
- return false;
-}
-
-void retro_unload_game(void)
-{
-}
-
unsigned retro_get_region(void)
{
return is_pal_mode ? RETRO_REGION_PAL : RETRO_REGION_NTSC;
@@ -915,6 +1364,8 @@ void *retro_get_memory_data(unsigned id)
{
if (id == RETRO_MEMORY_SAVE_RAM)
return Mcd1Data;
+ else if (id == RETRO_MEMORY_SYSTEM_RAM)
+ return psxM;
else
return NULL;
}
@@ -923,13 +1374,17 @@ size_t retro_get_memory_size(unsigned id)
{
if (id == RETRO_MEMORY_SAVE_RAM)
return MCD_SIZE;
+ else if (id == RETRO_MEMORY_SYSTEM_RAM)
+ return 0x210000;
else
return 0;
}
void retro_reset(void)
{
- SysReset();
+ //hack to prevent retroarch freezing when reseting in the menu but not while running with the hot key
+ rebootemu = 1;
+ //SysReset();
}
static const unsigned short retro_psx_map[] = {
@@ -955,20 +1410,19 @@ static const unsigned short retro_psx_map[] = {
static void update_variables(bool in_flight)
{
struct retro_variable var;
-
+ int i;
+
var.value = NULL;
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 = "pcsx_rearmed_region";
-
if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) || var.value)
{
Config.PsxAuto = 0;
- if (strcmp(var.value, "Automatic") == 0)
+ if (strcmp(var.value, "auto") == 0)
Config.PsxAuto = 1;
else if (strcmp(var.value, "NTSC") == 0)
Config.PsxType = 0;
@@ -976,24 +1430,61 @@ static void update_variables(bool in_flight)
Config.PsxType = 1;
}
+ for (i = 0; i < PORTS_NUMBER; i++)
+ update_controller_port_variable(i);
+
+ update_multitap();
+
var.value = NULL;
- var.key = "pcsx_rearmed_pad1type";
+ var.key = "pcsx_rearmed_negcon_deadzone";
+ negcon_deadzone = 0;
+ if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) || var.value)
+ {
+ negcon_deadzone = (int)(atoi(var.value) * 0.01f * NEGCON_RANGE);
+ }
+ var.value = NULL;
+ var.key = "pcsx_rearmed_negcon_response";
+ negcon_linearity = 1;
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;
+ if (strcmp(var.value, "quadratic") == 0){
+ negcon_linearity = 2;
+ } else if (strcmp(var.value, "cubic") == 0){
+ negcon_linearity = 3;
+ }
}
var.value = NULL;
- var.key = "pcsx_rearmed_pad2type";
+ var.key = "pcsx_rearmed_vibration";
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 (strcmp(var.value, "disabled") == 0)
+ in_enable_vibration = 0;
+ else if (strcmp(var.value, "enabled") == 0)
+ in_enable_vibration = 1;
+ }
+
+ var.value = NULL;
+ var.key = "pcsx_rearmed_dithering";
+
+ if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) || var.value)
+ {
+ if (strcmp(var.value, "disabled") == 0) {
+ pl_rearmed_cbs.gpu_peops.iUseDither = 0;
+ pl_rearmed_cbs.gpu_peopsgl.bDrawDither = 0;
+#ifdef __ARM_NEON__
+ pl_rearmed_cbs.gpu_neon.allow_dithering = 0;
+#endif
+ }
+ else if (strcmp(var.value, "enabled") == 0) {
+ pl_rearmed_cbs.gpu_peops.iUseDither = 1;
+ pl_rearmed_cbs.gpu_peopsgl.bDrawDither = 1;
+#ifdef __ARM_NEON__
+ pl_rearmed_cbs.gpu_neon.allow_dithering = 1;
+#endif
+ }
}
#ifdef __ARM_NEON__
@@ -1036,12 +1527,23 @@ static void update_variables(bool in_flight)
if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) || var.value)
{
- if (strcmp(var.value, "off") == 0)
+ if (strcmp(var.value, "disabled") == 0)
duping_enable = false;
- else if (strcmp(var.value, "on") == 0)
+ else if (strcmp(var.value, "enabled") == 0)
duping_enable = true;
}
+ var.value = "NULL";
+ var.key = "pcsx_rearmed_display_internal_fps";
+
+ if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) || var.value)
+ {
+ if (strcmp(var.value, "disabled") == 0)
+ display_internal_fps = false;
+ else if (strcmp(var.value, "enabled") == 0)
+ display_internal_fps = true;
+ }
+
#ifndef DRC_DISABLE
var.value = NULL;
var.key = "pcsx_rearmed_drc";
@@ -1050,6 +1552,11 @@ static void update_variables(bool in_flight)
{
R3000Acpu *prev_cpu = psxCpu;
+#ifdef _3DS
+ if(!__ctr_svchax)
+ Config.Cpu = CPU_INTERPRETER;
+ else
+#endif
if (strcmp(var.value, "disabled") == 0)
Config.Cpu = CPU_INTERPRETER;
else if (strcmp(var.value, "enabled") == 0)
@@ -1069,9 +1576,9 @@ static void update_variables(bool in_flight)
if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) || var.value)
{
- if (strcmp(var.value, "off") == 0)
+ if (strcmp(var.value, "disabled") == 0)
spu_config.iUseReverb = false;
- else if (strcmp(var.value, "on") == 0)
+ else if (strcmp(var.value, "enabled") == 0)
spu_config.iUseReverb = true;
}
@@ -1090,6 +1597,91 @@ static void update_variables(bool in_flight)
spu_config.iUseInterpolation = 0;
}
+ var.value = "NULL";
+ var.key = "pcsx_rearmed_pe2_fix";
+
+ if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) || var.value)
+ {
+ if (strcmp(var.value, "disabled") == 0)
+ Config.RCntFix = 0;
+ else if (strcmp(var.value, "enabled") == 0)
+ Config.RCntFix = 1;
+ }
+
+ var.value = "NULL";
+ var.key = "pcsx_rearmed_idiablofix";
+
+ if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) || var.value)
+ {
+ if (strcmp(var.value, "disabled") == 0)
+ spu_config.idiablofix = 0;
+ else if (strcmp(var.value, "enabled") == 0)
+ spu_config.idiablofix = 1;
+ }
+
+ var.value = "NULL";
+ var.key = "pcsx_rearmed_inuyasha_fix";
+
+ if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) || var.value)
+ {
+ if (strcmp(var.value, "disabled") == 0)
+ Config.VSyncWA = 0;
+ else if (strcmp(var.value, "enabled") == 0)
+ Config.VSyncWA = 1;
+ }
+
+ var.value = NULL;
+ var.key = "pcsx_rearmed_noxadecoding";
+ if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) || var.value)
+ {
+ if (strcmp(var.value, "disabled") == 0)
+ Config.Xa = 1;
+ else
+ Config.Xa = 0;
+ }
+
+ var.value = NULL;
+ var.key = "pcsx_rearmed_nocdaudio";
+ if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) || var.value)
+ {
+ if (strcmp(var.value, "disabled") == 0)
+ Config.Cdda = 1;
+ else
+ Config.Cdda = 0;
+ }
+
+#ifndef DRC_DISABLE
+ var.value = NULL;
+ var.key = "pcsx_rearmed_nosmccheck";
+ if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) || var.value)
+ {
+ if (strcmp(var.value, "enabled") == 0)
+ new_dynarec_hacks |= NDHACK_NO_SMC_CHECK;
+ else
+ new_dynarec_hacks &= ~NDHACK_NO_SMC_CHECK;
+ }
+
+ var.value = NULL;
+ var.key = "pcsx_rearmed_gteregsunneeded";
+ if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) || var.value)
+ {
+ if (strcmp(var.value, "enabled") == 0)
+ new_dynarec_hacks |= NDHACK_GTE_UNNEEDED;
+ else
+ new_dynarec_hacks &= ~NDHACK_GTE_UNNEEDED;
+ }
+
+ var.value = NULL;
+ var.key = "pcsx_rearmed_nogteflags";
+ if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) || var.value)
+ {
+ if (strcmp(var.value, "enabled") == 0)
+ new_dynarec_hacks |= NDHACK_GTE_NO_FLAGS;
+ else
+ new_dynarec_hacks &= ~NDHACK_GTE_NO_FLAGS;
+ }
+#endif
+
if (in_flight) {
// inform core things about possible config changes
plugin_call_rearmed_cbs();
@@ -1101,11 +1693,101 @@ static void update_variables(bool in_flight)
dfinput_activate();
}
+ else
+ {
+ //not yet running
+
+ //bootlogo display hack
+ if (found_bios) {
+ var.value = "NULL";
+ var.key = "pcsx_rearmed_show_bios_bootlogo";
+ if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) || var.value)
+ {
+ Config.SlowBoot = 0;
+ rebootemu = 0;
+ if (strcmp(var.value, "enabled") == 0)
+ {
+ Config.SlowBoot = 1;
+ rebootemu = 1;
+ }
+ }
+ }
+#ifndef DRC_DISABLE
+ var.value = "NULL";
+ var.key = "pcsx_rearmed_psxclock";
+ if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) || var.value)
+ {
+ int psxclock = atoi(var.value);
+ cycle_multiplier = 10000 / psxclock;
+ }
+#endif
+ }
+}
+
+// Taken from beetle-psx-libretro
+static uint16_t get_analog_button(int16_t ret, retro_input_state_t input_state_cb, int player_index, int id)
+{
+ // NOTE: Analog buttons were added Nov 2017. Not all front-ends support this
+ // feature (or pre-date it) so we need to handle this in a graceful way.
+
+ // First, try and get an analog value using the new libretro API constant
+ uint16_t button = input_state_cb(player_index,
+ RETRO_DEVICE_ANALOG,
+ RETRO_DEVICE_INDEX_ANALOG_BUTTON,
+ id);
+ button = MIN(button / 128, 255);
+
+ if (button == 0)
+ {
+ // If we got exactly zero, we're either not pressing the button, or the front-end
+ // is not reporting analog values. We need to do a second check using the classic
+ // digital API method, to at least get some response - better than nothing.
+
+ // NOTE: If we're really just not holding the button, we're still going to get zero.
+
+ button = (ret & (1 << id)) ? 255 : 0;
+ }
+
+ return button;
}
-void retro_run(void)
+void retro_run(void)
{
int i;
+ //SysReset must be run while core is running,Not in menu (Locks up Retroarch)
+ if (rebootemu != 0) {
+ rebootemu = 0;
+ SysReset();
+ if (!Config.HLE && !Config.SlowBoot) {
+ // skip BIOS logos
+ psxRegs.pc = psxRegs.GPR.n.ra;
+ }
+ }
+
+ if (display_internal_fps) {
+ frame_count++;
+
+ if (frame_count % INTERNAL_FPS_SAMPLE_PERIOD == 0) {
+ unsigned internal_fps = pl_rearmed_cbs.flip_cnt * (is_pal_mode ? 50 : 60) / INTERNAL_FPS_SAMPLE_PERIOD;
+ char str[64];
+ const char *strc = (const char*)str;
+ struct retro_message msg =
+ {
+ strc,
+ 180
+ };
+
+ str[0] = '\0';
+
+ snprintf(str, sizeof(str), "Internal FPS: %2d", internal_fps);
+
+ pl_rearmed_cbs.flip_cnt = 0;
+
+ environ_cb(RETRO_ENVIRONMENT_SET_MESSAGE, &msg);
+ }
+ }
+ else
+ frame_count = 0;
input_poll_cb();
@@ -1113,29 +1795,163 @@ void retro_run(void)
if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE_UPDATE, &updated) && updated)
update_variables(true);
- in_keystate = 0;
- for (i = 0; i < RETRO_PSX_MAP_LEN; i++)
- if (input_state_cb(1, RETRO_DEVICE_JOYPAD, 0, i))
- in_keystate |= retro_psx_map[i];
- in_keystate <<= 16;
- for (i = 0; i < RETRO_PSX_MAP_LEN; i++)
- if (input_state_cb(0, RETRO_DEVICE_JOYPAD, 0, i))
- in_keystate |= retro_psx_map[i];
+ // reset all keystate, query libretro for keystate
+ int j;
+ int lsx;
+ int rsy;
+ float negcon_twist_amplitude;
+ int negcon_i_rs;
+ int negcon_ii_rs;
+ for(i = 0; i < PORTS_NUMBER; i++)
+ {
+ int16_t ret = 0;
+ in_keystate[i] = 0;
- 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_type[i] == PSE_PAD_TYPE_NONE)
+ continue;
+
+ if (libretro_supports_bitmasks)
+ ret = input_state_cb(i, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_MASK);
+ else
+ {
+ unsigned j;
+ for (j = 0; j < (RETRO_DEVICE_ID_JOYPAD_R3+1); j++)
+ {
+ if (input_state_cb(i, RETRO_DEVICE_JOYPAD, 0, j))
+ ret |= (1 << j);
+ }
+ }
+
+ if (in_type[i] == PSE_PAD_TYPE_NEGCON)
+ {
+ // Query digital inputs
+ //
+ // > Pad-Up
+ if (ret & (1 << RETRO_DEVICE_ID_JOYPAD_UP))
+ in_keystate[i] |= (1 << DKEY_UP);
+ // > Pad-Right
+ if (ret & (1 << RETRO_DEVICE_ID_JOYPAD_RIGHT))
+ in_keystate[i] |= (1 << DKEY_RIGHT);
+ // > Pad-Down
+ if (ret & (1 << RETRO_DEVICE_ID_JOYPAD_DOWN))
+ in_keystate[i] |= (1 << DKEY_DOWN);
+ // > Pad-Left
+ if (ret & (1 << RETRO_DEVICE_ID_JOYPAD_LEFT))
+ in_keystate[i] |= (1 << DKEY_LEFT);
+ // > Start
+ if (ret & (1 << RETRO_DEVICE_ID_JOYPAD_START))
+ in_keystate[i] |= (1 << DKEY_START);
+ // > neGcon A
+ if (ret & (1 << RETRO_DEVICE_ID_JOYPAD_A))
+ in_keystate[i] |= (1 << DKEY_CIRCLE);
+ // > neGcon B
+ if (ret & (1 << RETRO_DEVICE_ID_JOYPAD_X))
+ in_keystate[i] |= (1 << DKEY_TRIANGLE);
+ // > neGcon R shoulder (digital)
+ if (ret & (1 << RETRO_DEVICE_ID_JOYPAD_R))
+ in_keystate[i] |= (1 << DKEY_R1);
+ // Query analog inputs
+ //
+ // From studying 'libpcsxcore/plugins.c' and 'frontend/plugin.c':
+ // >> pad->leftJoyX == in_analog_left[i][0] == NeGcon II
+ // >> pad->leftJoyY == in_analog_left[i][1] == NeGcon L
+ // >> pad->rightJoyX == in_analog_right[i][0] == NeGcon twist
+ // >> pad->rightJoyY == in_analog_right[i][1] == NeGcon I
+ // So we just have to map in_analog_left/right to more
+ // appropriate inputs...
+ //
+ // > NeGcon twist
+ // >> Get raw analog stick value and account for deadzone
+ lsx = input_state_cb(i, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_LEFT, RETRO_DEVICE_ID_ANALOG_X);
+ if (lsx > negcon_deadzone)
+ lsx = lsx - negcon_deadzone;
+ else if (lsx < -negcon_deadzone)
+ lsx = lsx + negcon_deadzone;
+ else
+ lsx = 0;
+ // >> Convert to an 'amplitude' [-1.0,1.0] and adjust response
+ negcon_twist_amplitude = (float)lsx / (float)(NEGCON_RANGE - negcon_deadzone);
+ if (negcon_linearity == 2)
+ {
+ if (negcon_twist_amplitude < 0.0)
+ negcon_twist_amplitude = -(negcon_twist_amplitude * negcon_twist_amplitude);
+ else
+ negcon_twist_amplitude = negcon_twist_amplitude * negcon_twist_amplitude;
+ }
+ else if (negcon_linearity == 3)
+ negcon_twist_amplitude = negcon_twist_amplitude * negcon_twist_amplitude * negcon_twist_amplitude;
+ // >> Convert to final 'in_analog' integer value [0,255]
+ in_analog_right[i][0] = MAX(MIN((int)(negcon_twist_amplitude * 128.0f) + 128, 255), 0);
+ // > NeGcon I + II
+ // >> Handle right analog stick vertical axis mapping...
+ // - Up (-Y) == accelerate == neGcon I
+ // - Down (+Y) == brake == neGcon II
+ negcon_i_rs = 0;
+ negcon_ii_rs = 0;
+ rsy = input_state_cb(i, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_RIGHT, RETRO_DEVICE_ID_ANALOG_Y);
+ if (rsy >= 0){
+ // Account for deadzone
+ // (Note: have never encountered a gamepad with significant differences
+ // in deadzone between left/right analog sticks, so use the regular 'twist'
+ // deadzone here)
+ if (rsy > negcon_deadzone)
+ rsy = rsy - negcon_deadzone;
+ else
+ rsy = 0;
+ // Convert to 'in_analog' integer value [0,255]
+ negcon_ii_rs = MIN((int)(((float)rsy / (float)(NEGCON_RANGE - negcon_deadzone)) * 255.0f), 255);
+ } else {
+ if (rsy < -negcon_deadzone)
+ rsy = -1 * (rsy + negcon_deadzone);
+ else
+ rsy = 0;
+ negcon_i_rs = MIN((int)(((float)rsy / (float)(NEGCON_RANGE - negcon_deadzone)) * 255.0f), 255);
+ }
+ // >> NeGcon I
+ in_analog_right[i][1] = MAX(
+ MAX(
+ get_analog_button(ret, input_state_cb, i, RETRO_DEVICE_ID_JOYPAD_R2),
+ get_analog_button(ret, input_state_cb, i, RETRO_DEVICE_ID_JOYPAD_B)
+ ),
+ negcon_i_rs
+ );
+ // >> NeGcon II
+ in_analog_left[i][0] = MAX(
+ MAX(
+ get_analog_button(ret, input_state_cb, i, RETRO_DEVICE_ID_JOYPAD_L2),
+ get_analog_button(ret, input_state_cb, i, RETRO_DEVICE_ID_JOYPAD_Y)
+ ),
+ negcon_ii_rs
+ );
+ // > NeGcon L
+ in_analog_left[i][1] = get_analog_button(ret, input_state_cb, i, RETRO_DEVICE_ID_JOYPAD_L);
+ }
+ else
+ {
+ // Query digital inputs
+ for (j = 0; j < RETRO_PSX_MAP_LEN; j++)
+ if (ret & (1 << j))
+ in_keystate[i] |= retro_psx_map[j];
+
+ // Query analog inputs
+ if (in_type[i] == PSE_PAD_TYPE_ANALOGJOY || in_type[i] == PSE_PAD_TYPE_ANALOGPAD)
+ {
+ in_analog_left[i][0] = MIN((input_state_cb(i, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_LEFT, RETRO_DEVICE_ID_ANALOG_X) / 255) + 128, 255);
+ in_analog_left[i][1] = MIN((input_state_cb(i, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_LEFT, RETRO_DEVICE_ID_ANALOG_Y) / 255) + 128, 255);
+ in_analog_right[i][0] = MIN((input_state_cb(i, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_RIGHT, RETRO_DEVICE_ID_ANALOG_X) / 255) + 128, 255);
+ in_analog_right[i][1] = MIN((input_state_cb(i, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_RIGHT, RETRO_DEVICE_ID_ANALOG_Y) / 255) + 128, 255);
+ }
+ }
}
stop = 0;
psxCpu->Execute();
- video_cb((vout_fb_dirty || !vout_can_dupe || !duping_enable) ? vout_buf : NULL,
+ video_cb((vout_fb_dirty || !vout_can_dupe || !duping_enable) ? vout_buf_ptr : NULL,
vout_width, vout_height, vout_width * 2);
vout_fb_dirty = 0;
+
+ set_vout_fb();
}
static bool try_use_bios(const char *path)
@@ -1162,7 +1978,7 @@ static bool try_use_bios(const char *path)
return true;
}
-#if 1
+#ifndef VITA
#include <sys/types.h>
#include <dirent.h>
@@ -1180,7 +1996,7 @@ static bool find_any_bios(const char *dirpath, char *path, size_t path_size)
if (strncasecmp(ent->d_name, "scph", 4) != 0)
continue;
- snprintf(path, path_size, "%s/%s", dirpath, ent->d_name);
+ snprintf(path, path_size, "%s%c%s", dirpath, SLASH, ent->d_name);
ret = try_use_bios(path);
if (ret)
break;
@@ -1198,63 +2014,155 @@ static void check_system_specs(void)
environ_cb(RETRO_ENVIRONMENT_SET_PERFORMANCE_LEVEL, &level);
}
-void retro_init(void)
+static int init_memcards(void)
+{
+ int ret = 0;
+ const char *dir;
+ struct retro_variable var = { .key="pcsx_rearmed_memcard2", .value=NULL };
+ static const char CARD2_FILE[] = "pcsx-card2.mcd";
+
+ // Memcard2 will be handled and is re-enabled if needed using core
+ // operations.
+ // Memcard1 is handled by libretro, doing this will set core to
+ // skip file io operations for memcard1 like SaveMcd
+ snprintf(Config.Mcd1, sizeof(Config.Mcd1), "none");
+ snprintf(Config.Mcd2, sizeof(Config.Mcd2), "none");
+ init_memcard(Mcd1Data);
+ // Memcard 2 is managed by the emulator on the filesystem,
+ // There is no need to initialize Mcd2Data like Mcd1Data.
+
+ if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) {
+ SysPrintf("Memcard 2: %s\n", var.value);
+ if (memcmp(var.value, "enabled", 7) == 0) {
+ if (environ_cb(RETRO_ENVIRONMENT_GET_SAVE_DIRECTORY, &dir) && dir) {
+ if (strlen(dir) + strlen(CARD2_FILE) + 2 > sizeof(Config.Mcd2)) {
+ SysPrintf("Path '%s' is too long. Cannot use memcard 2. Use a shorter path.\n", dir);
+ ret = -1;
+ } else {
+ McdDisable[1] = 0;
+ snprintf(Config.Mcd2, sizeof(Config.Mcd2), "%s/%s", dir, CARD2_FILE);
+ SysPrintf("Use memcard 2: %s\n", Config.Mcd2);
+ }
+ } else {
+ SysPrintf("Could not get save directory! Could not create memcard 2.");
+ ret = -1;
+ }
+ }
+ }
+ return ret;
+}
+
+static void loadPSXBios(void)
{
- const char *bios[] = { "scph1001", "scph5501", "scph7001" };
const char *dir;
char path[256];
- int i, ret;
- bool found_bios = false;
+ unsigned useHLE = 0;
+
+ const char *bios[] = {
+ "SCPH101", "scph101",
+ "SCPH5501", "scph5501",
+ "SCPH7001", "scph7001",
+ "SCPH1001", "scph1001"
+ };
+
+ struct retro_variable var = {
+ .key = "pcsx_rearmed_bios",
+ .value = NULL
+ };
+
+ found_bios = 0;
+
+ if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) {
+ if (!strcmp(var.value, "HLE"))
+ useHLE = 1;
+ }
+
+ if (!useHLE)
+ {
+ if (environ_cb(RETRO_ENVIRONMENT_GET_SYSTEM_DIRECTORY, &dir) && dir)
+ {
+ unsigned i;
+ snprintf(Config.BiosDir, sizeof(Config.BiosDir), "%s", dir);
+
+ for (i = 0; i < sizeof(bios) / sizeof(bios[0]); i++) {
+ snprintf(path, sizeof(path), "%s%c%s.bin", dir, SLASH, bios[i]);
+ found_bios = try_use_bios(path);
+ if (found_bios)
+ break;
+ }
+
+ if (!found_bios)
+ found_bios = find_any_bios(dir, path, sizeof(path));
+ }
+ if (found_bios) {
+ SysPrintf("found BIOS file: %s\n", Config.Bios);
+ }
+ }
+
+ if (useHLE || !found_bios)
+ {
+ SysPrintf("no BIOS files found.\n");
+ struct retro_message msg =
+ {
+ "No PlayStation BIOS file found - add for better compatibility",
+ 180
+ };
+ environ_cb(RETRO_ENVIRONMENT_SET_MESSAGE, (void*)&msg);
+ }
+}
+
+void retro_init(void)
+{
+ struct retro_rumble_interface rumble;
+ int ret;
#ifdef __MACH__
// magic sauce to make the dynarec work on iOS
syscall(SYS_ptrace, 0 /*PTRACE_TRACEME*/, 0, 0, 0);
#endif
+#ifdef _3DS
+ psxMapHook = pl_3ds_mmap;
+ psxUnmapHook = pl_3ds_munmap;
+#endif
+#ifdef VITA
+ if(init_vita_mmap()<0)
+ abort();
+ psxMapHook = pl_vita_mmap;
+ psxUnmapHook = pl_vita_munmap;
+#endif
ret = emu_core_preinit();
+#ifdef _3DS
+ /* emu_core_preinit sets the cpu to dynarec */
+ if(!__ctr_svchax)
+ Config.Cpu = CPU_INTERPRETER;
+#endif
+ ret |= init_memcards();
+
ret |= emu_core_init();
if (ret != 0) {
SysPrintf("PCSX init failed.\n");
exit(1);
}
-#if defined(_POSIX_C_SOURCE) && (_POSIX_C_SOURCE >= 200112L)
+#ifdef _3DS
+ vout_buf = linearMemAlign(VOUT_MAX_WIDTH * VOUT_MAX_HEIGHT * 2, 0x80);
+#elif defined(_POSIX_C_SOURCE) && (_POSIX_C_SOURCE >= 200112L) && !defined(VITA)
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)
- {
- snprintf(Config.BiosDir, sizeof(Config.BiosDir), "%s/", dir);
+ vout_buf_ptr = vout_buf;
- for (i = 0; i < sizeof(bios) / sizeof(bios[0]); i++) {
- snprintf(path, sizeof(path), "%s/%s.bin", dir, bios[i]);
- found_bios = try_use_bios(path);
- if (found_bios)
- break;
- }
-
- if (!found_bios)
- found_bios = find_any_bios(dir, path, sizeof(path));
- }
- if (found_bios) {
- SysPrintf("found BIOS file: %s\n", Config.Bios);
- }
- else
- {
- SysPrintf("no BIOS files found.\n");
- struct retro_message msg =
- {
- "no BIOS found, expect bugs!",
- 180
- };
- environ_cb(RETRO_ENVIRONMENT_SET_MESSAGE, (void*)&msg);
- }
+ loadPSXBios();
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);
+
+ rumble_cb = NULL;
+ if (environ_cb(RETRO_ENVIRONMENT_GET_RUMBLE_INTERFACE, &rumble))
+ rumble_cb = rumble.set_rumble_state;
/* 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
@@ -1266,16 +2174,15 @@ void retro_init(void)
pl_rearmed_cbs.gpu_peops.iUseDither = 1;
spu_config.iUseFixedUpdates = 1;
- McdDisable[0] = 0;
- McdDisable[1] = 1;
- init_memcard(Mcd1Data);
-
SaveFuncs.open = save_open;
SaveFuncs.read = save_read;
SaveFuncs.write = save_write;
SaveFuncs.seek = save_seek;
SaveFuncs.close = save_close;
+ if (environ_cb(RETRO_ENVIRONMENT_GET_INPUT_BITMASKS, NULL))
+ libretro_supports_bitmasks = true;
+
update_variables(false);
check_system_specs();
}
@@ -1283,6 +2190,23 @@ void retro_init(void)
void retro_deinit(void)
{
SysClose();
+#ifdef _3DS
+ linearFree(vout_buf);
+#else
free(vout_buf);
+#endif
vout_buf = NULL;
+
+#ifdef VITA
+ deinit_vita_mmap();
+#endif
+ libretro_supports_bitmasks = false;
}
+
+#ifdef VITA
+#include <psp2/kernel/threadmgr.h>
+int usleep (unsigned long us)
+{
+ sceKernelDelayThread(us);
+}
+#endif
diff --git a/frontend/libretro.h b/frontend/libretro.h
index 16c274a..8daec83 100755
--- a/frontend/libretro.h
+++ b/frontend/libretro.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2010-2014 The RetroArch team
+/* Copyright (C) 2010-2018 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this libretro API header (libretro.h).
@@ -32,7 +32,7 @@ extern "C" {
#endif
#ifndef __cplusplus
-#if defined(_MSC_VER) && !defined(SN_TARGET_PS3)
+#if defined(_MSC_VER) && _MSC_VER < 1800 && !defined(SN_TARGET_PS3)
/* Hack applied for MSVC when compiling in C89 mode
* as it isn't C99-compliant. */
#define bool unsigned char
@@ -43,7 +43,41 @@ extern "C" {
#endif
#endif
-/* Used for checking API/ABI mismatches that can break libretro
+#ifndef RETRO_CALLCONV
+# if defined(__GNUC__) && defined(__i386__) && !defined(__x86_64__)
+# define RETRO_CALLCONV __attribute__((cdecl))
+# elif defined(_MSC_VER) && defined(_M_X86) && !defined(_M_X64)
+# define RETRO_CALLCONV __cdecl
+# else
+# define RETRO_CALLCONV /* all other platforms only have one calling convention each */
+# endif
+#endif
+
+#ifndef RETRO_API
+# if defined(_WIN32) || defined(__CYGWIN__) || defined(__MINGW32__)
+# ifdef RETRO_IMPORT_SYMBOLS
+# ifdef __GNUC__
+# define RETRO_API RETRO_CALLCONV __attribute__((__dllimport__))
+# else
+# define RETRO_API RETRO_CALLCONV __declspec(dllimport)
+# endif
+# else
+# ifdef __GNUC__
+# define RETRO_API RETRO_CALLCONV __attribute__((__dllexport__))
+# else
+# define RETRO_API RETRO_CALLCONV __declspec(dllexport)
+# endif
+# endif
+# else
+# if defined(__GNUC__) && __GNUC__ >= 4 && !defined(__CELLOS_LV2__)
+# define RETRO_API RETRO_CALLCONV __attribute__((__visibility__("default")))
+# else
+# define RETRO_API RETRO_CALLCONV
+# endif
+# endif
+#endif
+
+/* Used for checking API/ABI mismatches that can break libretro
* implementations.
* It is not incremented for compatible changes to the API.
*/
@@ -53,13 +87,13 @@ extern "C" {
* 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
+ * such as a joypad (with/without analog), mouse, keyboard, lightgun
* and a pointer.
*
- * The functionality of these devices are fixed, and individual cores
+ * 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
+ * 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.
*/
@@ -70,43 +104,52 @@ extern "C" {
/* 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
+/* 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
+ * 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
+ * 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
+ * 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 device is similar to Guncon-2 for PlayStation 2.
+ * It reports X/Y coordinates in screen space (similar to the pointer)
+ * in the range [-0x8000, 0x7fff] in both axes, with zero being center and
+ * -0x8000 being out of bounds.
+ * As well as reporting on/off screen state. It features a trigger,
+ * start/select buttons, auxiliary action buttons and a
+ * directional pad. A forced off-screen shot can be requested for
+ * auto-reloading function in some games.
+ */
#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.
+ * Similar to DualShock2 it adds two analog sticks and all buttons can
+ * be analog. This is treated as a separate device type as it returns
+ * axis values in the full analog range of [-0x7fff, 0x7fff],
+ * although some devices may return -0x8000.
+ * Positive X axis is right. Positive Y axis is down.
+ * Buttons are returned in the range [0, 0x7fff].
+ * Only use ANALOG type when polling for analog values.
*/
#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
+ * 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.
@@ -114,33 +157,34 @@ extern "C" {
* 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
+ * 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
+ * (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
+ * 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
+ * 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
+ * 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
+ * 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
+ * Eventually _PRESSED will return false for an index. No further presses
* are registered at this point. */
#define RETRO_DEVICE_POINTER 6
/* Buttons for the RetroPad (JOYPAD).
- * The placement of these is equivalent to placements on the
+ * The placement of these is equivalent to placements on the
* Super Nintendo controller.
- * L2/R2/L3/R3 buttons correspond to the PS1 DualShock. */
+ * L2/R2/L3/R3 buttons correspond to the PS1 DualShock.
+ * Also used as id values for RETRO_DEVICE_INDEX_ANALOG_BUTTON */
#define RETRO_DEVICE_ID_JOYPAD_B 0
#define RETRO_DEVICE_ID_JOYPAD_Y 1
#define RETRO_DEVICE_ID_JOYPAD_SELECT 2
@@ -158,34 +202,55 @@ extern "C" {
#define RETRO_DEVICE_ID_JOYPAD_L3 14
#define RETRO_DEVICE_ID_JOYPAD_R3 15
+#define RETRO_DEVICE_ID_JOYPAD_MASK 256
+
/* 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
+#define RETRO_DEVICE_INDEX_ANALOG_LEFT 0
+#define RETRO_DEVICE_INDEX_ANALOG_RIGHT 1
+#define RETRO_DEVICE_INDEX_ANALOG_BUTTON 2
+#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
-#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. */
-#define RETRO_DEVICE_ID_LIGHTGUN_X 0
-#define RETRO_DEVICE_ID_LIGHTGUN_Y 1
-#define RETRO_DEVICE_ID_LIGHTGUN_TRIGGER 2
-#define RETRO_DEVICE_ID_LIGHTGUN_CURSOR 3
-#define RETRO_DEVICE_ID_LIGHTGUN_TURBO 4
-#define RETRO_DEVICE_ID_LIGHTGUN_PAUSE 5
-#define RETRO_DEVICE_ID_LIGHTGUN_START 6
+#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
+#define RETRO_DEVICE_ID_MOUSE_HORIZ_WHEELUP 7
+#define RETRO_DEVICE_ID_MOUSE_HORIZ_WHEELDOWN 8
+#define RETRO_DEVICE_ID_MOUSE_BUTTON_4 9
+#define RETRO_DEVICE_ID_MOUSE_BUTTON_5 10
+
+/* Id values for LIGHTGUN. */
+#define RETRO_DEVICE_ID_LIGHTGUN_SCREEN_X 13 /*Absolute Position*/
+#define RETRO_DEVICE_ID_LIGHTGUN_SCREEN_Y 14 /*Absolute*/
+#define RETRO_DEVICE_ID_LIGHTGUN_IS_OFFSCREEN 15 /*Status Check*/
+#define RETRO_DEVICE_ID_LIGHTGUN_TRIGGER 2
+#define RETRO_DEVICE_ID_LIGHTGUN_RELOAD 16 /*Forced off-screen shot*/
+#define RETRO_DEVICE_ID_LIGHTGUN_AUX_A 3
+#define RETRO_DEVICE_ID_LIGHTGUN_AUX_B 4
+#define RETRO_DEVICE_ID_LIGHTGUN_START 6
+#define RETRO_DEVICE_ID_LIGHTGUN_SELECT 7
+#define RETRO_DEVICE_ID_LIGHTGUN_AUX_C 8
+#define RETRO_DEVICE_ID_LIGHTGUN_DPAD_UP 9
+#define RETRO_DEVICE_ID_LIGHTGUN_DPAD_DOWN 10
+#define RETRO_DEVICE_ID_LIGHTGUN_DPAD_LEFT 11
+#define RETRO_DEVICE_ID_LIGHTGUN_DPAD_RIGHT 12
+/* deprecated */
+#define RETRO_DEVICE_ID_LIGHTGUN_X 0 /*Relative Position*/
+#define RETRO_DEVICE_ID_LIGHTGUN_Y 1 /*Relative*/
+#define RETRO_DEVICE_ID_LIGHTGUN_CURSOR 3 /*Use Aux:A*/
+#define RETRO_DEVICE_ID_LIGHTGUN_TURBO 4 /*Use Aux:B*/
+#define RETRO_DEVICE_ID_LIGHTGUN_PAUSE 5 /*Use Start*/
/* 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
+#define RETRO_DEVICE_ID_POINTER_COUNT 3
/* Returned from retro_get_region(). */
#define RETRO_REGION_NTSC 0
@@ -194,26 +259,33 @@ extern "C" {
/* 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_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_BRAZIL = 7,
+ RETRO_LANGUAGE_PORTUGUESE_PORTUGAL = 8,
+ RETRO_LANGUAGE_RUSSIAN = 9,
+ RETRO_LANGUAGE_KOREAN = 10,
+ RETRO_LANGUAGE_CHINESE_TRADITIONAL = 11,
+ RETRO_LANGUAGE_CHINESE_SIMPLIFIED = 12,
+ RETRO_LANGUAGE_ESPERANTO = 13,
+ RETRO_LANGUAGE_POLISH = 14,
+ RETRO_LANGUAGE_VIETNAMESE = 15,
+ RETRO_LANGUAGE_ARABIC = 16,
+ RETRO_LANGUAGE_GREEK = 17,
+ RETRO_LANGUAGE_TURKISH = 18,
RETRO_LANGUAGE_LAST,
/* Ensure sizeof(enum) == sizeof(int) */
- RETRO_LANGUAGE_DUMMY = INT_MAX
+ RETRO_LANGUAGE_DUMMY = INT_MAX
};
/* Passed to retro_get_memory_data/size().
- * If the memory type doesn't apply to the
+ * If the memory type doesn't apply to the
* implementation NULL/0 can be returned.
*/
#define RETRO_MEMORY_MASK 0xff
@@ -311,6 +383,10 @@ enum retro_key
RETROK_x = 120,
RETROK_y = 121,
RETROK_z = 122,
+ RETROK_LEFTBRACE = 123,
+ RETROK_BAR = 124,
+ RETROK_RIGHTBRACE = 125,
+ RETROK_TILDE = 126,
RETROK_DELETE = 127,
RETROK_KP0 = 256,
@@ -381,6 +457,7 @@ enum retro_key
RETROK_POWER = 320,
RETROK_EURO = 321,
RETROK_UNDO = 322,
+ RETROK_OEM_102 = 323,
RETROK_LAST,
@@ -403,7 +480,7 @@ 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
+/* 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. */
@@ -412,12 +489,14 @@ enum retro_mod
/* 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,
+ * 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,
+ * NOTE: As of 2019 this callback is considered deprecated in favor of
+ * using core options to manage overscan in a more nuanced, core-specific way.
+ *
+ * Boolean value whether or not the implementation should use overscan,
* or crop away overscan.
*/
#define RETRO_ENVIRONMENT_GET_CAN_DUPE 3 /* bool * --
@@ -425,15 +504,15 @@ enum retro_mod
* passing NULL to video frame callback.
*/
- /* Environ 4, 5 are no longer supported (GET_VARIABLE / SET_VARIABLES),
+ /* 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
+ * 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
+ * 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) --
@@ -461,15 +540,15 @@ enum retro_mod
#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
+ * 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
+ * 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
+ * This is now discouraged, and if possible, cores should try to
* use the new GET_SAVE_DIRECTORY.
*/
#define RETRO_ENVIRONMENT_SET_PIXEL_FORMAT 10
@@ -477,19 +556,19 @@ enum retro_mod
* 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
+ * If the call returns false, the frontend does not support this pixel
* format.
*
- * This function should be called inside retro_load_game() or
+ * 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
+ * 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
+ * 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
@@ -498,52 +577,55 @@ enum retro_mod
*/
#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
+ * Sets an interface which frontend can use to eject and insert
* disk images.
- * This is used for games which consist of multiple images and
+ * 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
+ * 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
+ * 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
+ * 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
+ * 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
+ * '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
+ * which variables it might want to check for later using
* GET_VARIABLE.
- * This allows the frontend to present these variables to
+ * 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
+ * This should be called the first time as early as
+ * possible (ideally in retro_set_environment).
+ * Afterward it may be called again for the core to communicate
+ * updated options to the frontend, but the number of core
+ * options must not change from the number in the initial call.
+ *
+ * '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
+ * 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
+ * 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
+ * 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.
@@ -551,11 +633,11 @@ enum retro_mod
* 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
+ * 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
+ * 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
@@ -566,72 +648,72 @@ enum retro_mod
*/
#define RETRO_ENVIRONMENT_SET_SUPPORT_NO_GAME 18
/* const bool * --
- * If true, the libretro implementation supports calls to
+ * 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
+ * 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
+ * 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
+ * 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.
+
+ /* 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_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_SET_AUDIO_CALLBACK 22
/* const struct retro_audio_callback * --
- * Sets an interface which is used to notify a libretro core about audio
+ * 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
+ * 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
+ * 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
+ * This interface is not recommended for use with emulators which have
* highly synchronous audio.
*
- * The callback only notifies about writability; the libretro core still
+ * 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
+ * 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
+ * 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
+ * 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
+ * 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
+ * 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
+ * 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
+ * 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().
@@ -640,63 +722,64 @@ enum retro_mod
/* 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,
+ * setting state related to sensors such as polling rate,
* enabling/disable it entirely, etc.
- * Reading sensor state is done via the normal
+ * 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
+ * A libretro core can use this interface to get access to a
* video camera.
- * New video frames are delivered in a callback in same
+ * 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
+ * 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
+ * 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
+ * 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
+ * It is recommended to use a libretro GL core when
* using camera interface.
*
- * The camera is not started automatically. The retrieved start/stop
+ * 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
+ * Gets an interface for logging. This is useful for
* logging in a cross-platform way
- * as certain platforms cannot use use stderr for logging.
+ * as certain platforms cannot 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
+ * 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
+ * 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
+ * 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
+#define RETRO_ENVIRONMENT_GET_CONTENT_DIRECTORY 30 /* Old name, kept for compatibility. */
+#define RETRO_ENVIRONMENT_GET_CORE_ASSETS_DIRECTORY 30
/* const char ** --
- * Returns the "content" directory of the frontend.
- * This directory can be used to store specific assets that the
+ * Returns the "core assets" 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.
@@ -705,76 +788,77 @@ enum retro_mod
*/
#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
+ * Returns the "save" directory of the frontend, unless there is no
+ * save directory available. The save directory should 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.
+ * If the frontend cannot designate a save directory, it will return
+ * NULL to indicate that the core should attempt to operate without a
+ * save directory set.
+ *
+ * NOTE: early libretro cores used the system directory for save
+ * files. Cores that need to be backwards-compatible can still check
+ * GET_SYSTEM_DIRECTORY.
*/
#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
+ * 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
+ * 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
+ * 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
+ * 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
+ * An eventual driver reinitialize will happen so that video and
* audio callbacks
- * happening after this call within the same retro_run() call will
+ * 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
+ * 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
+ * ***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
+ * 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
+ * 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
+ * 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
+ * Allows a libretro core to announce support for the
* get_proc_address() interface.
- * This interface allows for a standard way to extend libretro where
+ * 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
+ * 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
+ * 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
+ * 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
+ * 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
+ * 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
+ * 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
@@ -782,68 +866,81 @@ enum retro_mod
*/
#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
+ * This environment call lets a libretro core tell the frontend
+ * which controller subclasses 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.
+ * 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 specifcally
+ * provided by the Libretro 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.
+ * In order for a frontend to understand the workings of those devices,
+ * they must be defined as a specialized subclass 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,
+ * The core must pass an array of const struct retro_controller_info which
+ * is terminated with a blanked out struct. Each element of the
+ * retro_controller_info struct corresponds to the ascending port index
+ * that is passed to retro_set_controller_port_device() when that function
+ * is called to indicate to the core that the frontend has changed the
+ * active device subclass. SEE ALSO: retro_set_controller_port_device()
+ *
+ * The ascending input port indexes provided by the core in the struct
+ * are generally presented by frontends as ascending User # or Player #,
+ * such as Player 1, Player 2, Player 3, etc. Which device subclasses are
+ * supported can vary per input port.
+ *
+ * The first inner element of each entry in the retro_controller_info array
+ * is a retro_controller_description struct that specifies the names and
+ * codes of all device subclasses that are available for the corresponding
+ * User or Player, beginning with the generic Libretro device that the
+ * subclasses are derived from. The second inner element of each entry is the
+ * total number of subclasses that are listed in the retro_controller_description.
+ *
+ * NOTE: 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
+ * 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
+ * Should only be used by emulators; it doesn't make much sense for
* anything else.
- * It is recommended to expose all relevant pointers through
+ * 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
+ * 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
+ * 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
+ * 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
+ * A frontend must guarantee that this environment call completes in
* constant time.
*/
-#define RETRO_ENVIRONMENT_GET_USERNAME 38
+#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
+ * 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,
+ * 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
@@ -851,70 +948,495 @@ enum retro_mod
* Returns the specified language of the frontend, if specified by the user.
* It can be used by the core for localization purposes.
*/
+#define RETRO_ENVIRONMENT_GET_CURRENT_SOFTWARE_FRAMEBUFFER (40 | RETRO_ENVIRONMENT_EXPERIMENTAL)
+ /* struct retro_framebuffer * --
+ * Returns a preallocated framebuffer which the core can use for rendering
+ * the frame into when not using SET_HW_RENDER.
+ * The framebuffer returned from this call must not be used
+ * after the current call to retro_run() returns.
+ *
+ * The goal of this call is to allow zero-copy behavior where a core
+ * can render directly into video memory, avoiding extra bandwidth cost by copying
+ * memory from core to video memory.
+ *
+ * If this call succeeds and the core renders into it,
+ * the framebuffer pointer and pitch can be passed to retro_video_refresh_t.
+ * If the buffer from GET_CURRENT_SOFTWARE_FRAMEBUFFER is to be used,
+ * the core must pass the exact
+ * same pointer as returned by GET_CURRENT_SOFTWARE_FRAMEBUFFER;
+ * i.e. passing a pointer which is offset from the
+ * buffer is undefined. The width, height and pitch parameters
+ * must also match exactly to the values obtained from GET_CURRENT_SOFTWARE_FRAMEBUFFER.
+ *
+ * It is possible for a frontend to return a different pixel format
+ * than the one used in SET_PIXEL_FORMAT. This can happen if the frontend
+ * needs to perform conversion.
+ *
+ * It is still valid for a core to render to a different buffer
+ * even if GET_CURRENT_SOFTWARE_FRAMEBUFFER succeeds.
+ *
+ * A frontend must make sure that the pointer obtained from this function is
+ * writeable (and readable).
+ */
+#define RETRO_ENVIRONMENT_GET_HW_RENDER_INTERFACE (41 | RETRO_ENVIRONMENT_EXPERIMENTAL)
+ /* const struct retro_hw_render_interface ** --
+ * Returns an API specific rendering interface for accessing API specific data.
+ * Not all HW rendering APIs support or need this.
+ * The contents of the returned pointer is specific to the rendering API
+ * being used. See the various headers like libretro_vulkan.h, etc.
+ *
+ * GET_HW_RENDER_INTERFACE cannot be called before context_reset has been called.
+ * Similarly, after context_destroyed callback returns,
+ * the contents of the HW_RENDER_INTERFACE are invalidated.
+ */
+#define RETRO_ENVIRONMENT_SET_SUPPORT_ACHIEVEMENTS (42 | RETRO_ENVIRONMENT_EXPERIMENTAL)
+ /* const bool * --
+ * If true, the libretro implementation supports achievements
+ * either via memory descriptors set with RETRO_ENVIRONMENT_SET_MEMORY_MAPS
+ * or via retro_get_memory_data/retro_get_memory_size.
+ *
+ * This must be called before the first call to retro_run.
+ */
+#define RETRO_ENVIRONMENT_SET_HW_RENDER_CONTEXT_NEGOTIATION_INTERFACE (43 | RETRO_ENVIRONMENT_EXPERIMENTAL)
+ /* const struct retro_hw_render_context_negotiation_interface * --
+ * Sets an interface which lets the libretro core negotiate with frontend how a context is created.
+ * The semantics of this interface depends on which API is used in SET_HW_RENDER earlier.
+ * This interface will be used when the frontend is trying to create a HW rendering context,
+ * so it will be used after SET_HW_RENDER, but before the context_reset callback.
+ */
+#define RETRO_ENVIRONMENT_SET_SERIALIZATION_QUIRKS 44
+ /* uint64_t * --
+ * Sets quirk flags associated with serialization. The frontend will zero any flags it doesn't
+ * recognize or support. Should be set in either retro_init or retro_load_game, but not both.
+ */
+#define RETRO_ENVIRONMENT_SET_HW_SHARED_CONTEXT (44 | RETRO_ENVIRONMENT_EXPERIMENTAL)
+ /* N/A (null) * --
+ * The frontend will try to use a 'shared' hardware context (mostly applicable
+ * to OpenGL) when a hardware context is being set up.
+ *
+ * Returns true if the frontend supports shared hardware contexts and false
+ * if the frontend does not support shared hardware contexts.
+ *
+ * This will do nothing on its own until SET_HW_RENDER env callbacks are
+ * being used.
+ */
+#define RETRO_ENVIRONMENT_GET_VFS_INTERFACE (45 | RETRO_ENVIRONMENT_EXPERIMENTAL)
+ /* struct retro_vfs_interface_info * --
+ * Gets access to the VFS interface.
+ * VFS presence needs to be queried prior to load_game or any
+ * get_system/save/other_directory being called to let front end know
+ * core supports VFS before it starts handing out paths.
+ * It is recomended to do so in retro_set_environment
+ */
+#define RETRO_ENVIRONMENT_GET_LED_INTERFACE (46 | RETRO_ENVIRONMENT_EXPERIMENTAL)
+ /* struct retro_led_interface * --
+ * Gets an interface which is used by a libretro core to set
+ * state of LEDs.
+ */
+#define RETRO_ENVIRONMENT_GET_AUDIO_VIDEO_ENABLE (47 | RETRO_ENVIRONMENT_EXPERIMENTAL)
+ /* int * --
+ * Tells the core if the frontend wants audio or video.
+ * If disabled, the frontend will discard the audio or video,
+ * so the core may decide to skip generating a frame or generating audio.
+ * This is mainly used for increasing performance.
+ * Bit 0 (value 1): Enable Video
+ * Bit 1 (value 2): Enable Audio
+ * Bit 2 (value 4): Use Fast Savestates.
+ * Bit 3 (value 8): Hard Disable Audio
+ * Other bits are reserved for future use and will default to zero.
+ * If video is disabled:
+ * * The frontend wants the core to not generate any video,
+ * including presenting frames via hardware acceleration.
+ * * The frontend's video frame callback will do nothing.
+ * * After running the frame, the video output of the next frame should be
+ * no different than if video was enabled, and saving and loading state
+ * should have no issues.
+ * If audio is disabled:
+ * * The frontend wants the core to not generate any audio.
+ * * The frontend's audio callbacks will do nothing.
+ * * After running the frame, the audio output of the next frame should be
+ * no different than if audio was enabled, and saving and loading state
+ * should have no issues.
+ * Fast Savestates:
+ * * Guaranteed to be created by the same binary that will load them.
+ * * Will not be written to or read from the disk.
+ * * Suggest that the core assumes loading state will succeed.
+ * * Suggest that the core updates its memory buffers in-place if possible.
+ * * Suggest that the core skips clearing memory.
+ * * Suggest that the core skips resetting the system.
+ * * Suggest that the core may skip validation steps.
+ * Hard Disable Audio:
+ * * Used for a secondary core when running ahead.
+ * * Indicates that the frontend will never need audio from the core.
+ * * Suggests that the core may stop synthesizing audio, but this should not
+ * compromise emulation accuracy.
+ * * Audio output for the next frame does not matter, and the frontend will
+ * never need an accurate audio state in the future.
+ * * State will never be saved when using Hard Disable Audio.
+ */
+#define RETRO_ENVIRONMENT_GET_MIDI_INTERFACE (48 | RETRO_ENVIRONMENT_EXPERIMENTAL)
+ /* struct retro_midi_interface ** --
+ * Returns a MIDI interface that can be used for raw data I/O.
+ */
+
+#define RETRO_ENVIRONMENT_GET_FASTFORWARDING (49 | RETRO_ENVIRONMENT_EXPERIMENTAL)
+ /* bool * --
+ * Boolean value that indicates whether or not the frontend is in
+ * fastforwarding mode.
+ */
+
+#define RETRO_ENVIRONMENT_GET_TARGET_REFRESH_RATE (50 | RETRO_ENVIRONMENT_EXPERIMENTAL)
+ /* float * --
+ * Float value that lets us know what target refresh rate
+ * is curently in use by the frontend.
+ *
+ * The core can use the returned value to set an ideal
+ * refresh rate/framerate.
+ */
+
+#define RETRO_ENVIRONMENT_GET_INPUT_BITMASKS (51 | RETRO_ENVIRONMENT_EXPERIMENTAL)
+ /* bool * --
+ * Boolean value that indicates whether or not the frontend supports
+ * input bitmasks being returned by retro_input_state_t. The advantage
+ * of this is that retro_input_state_t has to be only called once to
+ * grab all button states instead of multiple times.
+ *
+ * If it returns true, you can pass RETRO_DEVICE_ID_JOYPAD_MASK as 'id'
+ * to retro_input_state_t (make sure 'device' is set to RETRO_DEVICE_JOYPAD).
+ * It will return a bitmask of all the digital buttons.
+ */
-#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)
+/* VFS functionality */
+
+/* File paths:
+ * File paths passed as parameters when using this API shall be well formed UNIX-style,
+ * using "/" (unquoted forward slash) as directory separator regardless of the platform's native separator.
+ * Paths shall also include at least one forward slash ("game.bin" is an invalid path, use "./game.bin" instead).
+ * Other than the directory separator, cores shall not make assumptions about path format:
+ * "C:/path/game.bin", "http://example.com/game.bin", "#game/game.bin", "./game.bin" (without quotes) are all valid paths.
+ * Cores may replace the basename or remove path components from the end, and/or add new components;
+ * however, cores shall not append "./", "../" or multiple consecutive forward slashes ("//") to paths they request to front end.
+ * The frontend is encouraged to make such paths work as well as it can, but is allowed to give up if the core alters paths too much.
+ * Frontends are encouraged, but not required, to support native file system paths (modulo replacing the directory separator, if applicable).
+ * Cores are allowed to try using them, but must remain functional if the front rejects such requests.
+ * Cores are encouraged to use the libretro-common filestream functions for file I/O,
+ * as they seamlessly integrate with VFS, deal with directory separator replacement as appropriate
+ * and provide platform-specific fallbacks in cases where front ends do not support VFS. */
+
+/* Opaque file handle
+ * Introduced in VFS API v1 */
+struct retro_vfs_file_handle;
+
+/* Opaque directory handle
+ * Introduced in VFS API v3 */
+struct retro_vfs_dir_handle;
+
+/* File open flags
+ * Introduced in VFS API v1 */
+#define RETRO_VFS_FILE_ACCESS_READ (1 << 0) /* Read only mode */
+#define RETRO_VFS_FILE_ACCESS_WRITE (1 << 1) /* Write only mode, discard contents and overwrites existing file unless RETRO_VFS_FILE_ACCESS_UPDATE is also specified */
+#define RETRO_VFS_FILE_ACCESS_READ_WRITE (RETRO_VFS_FILE_ACCESS_READ | RETRO_VFS_FILE_ACCESS_WRITE) /* Read-write mode, discard contents and overwrites existing file unless RETRO_VFS_FILE_ACCESS_UPDATE is also specified*/
+#define RETRO_VFS_FILE_ACCESS_UPDATE_EXISTING (1 << 2) /* Prevents discarding content of existing files opened for writing */
+
+/* These are only hints. The frontend may choose to ignore them. Other than RAM/CPU/etc use,
+ and how they react to unlikely external interference (for example someone else writing to that file,
+ or the file's server going down), behavior will not change. */
+#define RETRO_VFS_FILE_ACCESS_HINT_NONE (0)
+/* Indicate that the file will be accessed many times. The frontend should aggressively cache everything. */
+#define RETRO_VFS_FILE_ACCESS_HINT_FREQUENT_ACCESS (1 << 0)
+
+/* Seek positions */
+#define RETRO_VFS_SEEK_POSITION_START 0
+#define RETRO_VFS_SEEK_POSITION_CURRENT 1
+#define RETRO_VFS_SEEK_POSITION_END 2
+
+/* stat() result flags
+ * Introduced in VFS API v3 */
+#define RETRO_VFS_STAT_IS_VALID (1 << 0)
+#define RETRO_VFS_STAT_IS_DIRECTORY (1 << 1)
+#define RETRO_VFS_STAT_IS_CHARACTER_SPECIAL (1 << 2)
+
+/* Get path from opaque handle. Returns the exact same path passed to file_open when getting the handle
+ * Introduced in VFS API v1 */
+typedef const char *(RETRO_CALLCONV *retro_vfs_get_path_t)(struct retro_vfs_file_handle *stream);
+
+/* Open a file for reading or writing. If path points to a directory, this will
+ * fail. Returns the opaque file handle, or NULL for error.
+ * Introduced in VFS API v1 */
+typedef struct retro_vfs_file_handle *(RETRO_CALLCONV *retro_vfs_open_t)(const char *path, unsigned mode, unsigned hints);
+
+/* Close the file and release its resources. Must be called if open_file returns non-NULL. Returns 0 on success, -1 on failure.
+ * Whether the call succeeds ot not, the handle passed as parameter becomes invalid and should no longer be used.
+ * Introduced in VFS API v1 */
+typedef int (RETRO_CALLCONV *retro_vfs_close_t)(struct retro_vfs_file_handle *stream);
+
+/* Return the size of the file in bytes, or -1 for error.
+ * Introduced in VFS API v1 */
+typedef int64_t (RETRO_CALLCONV *retro_vfs_size_t)(struct retro_vfs_file_handle *stream);
+
+/* Truncate file to specified size. Returns 0 on success or -1 on error
+ * Introduced in VFS API v2 */
+typedef int64_t (RETRO_CALLCONV *retro_vfs_truncate_t)(struct retro_vfs_file_handle *stream, int64_t length);
+
+/* Get the current read / write position for the file. Returns -1 for error.
+ * Introduced in VFS API v1 */
+typedef int64_t (RETRO_CALLCONV *retro_vfs_tell_t)(struct retro_vfs_file_handle *stream);
+
+/* Set the current read/write position for the file. Returns the new position, -1 for error.
+ * Introduced in VFS API v1 */
+typedef int64_t (RETRO_CALLCONV *retro_vfs_seek_t)(struct retro_vfs_file_handle *stream, int64_t offset, int seek_position);
+
+/* Read data from a file. Returns the number of bytes read, or -1 for error.
+ * Introduced in VFS API v1 */
+typedef int64_t (RETRO_CALLCONV *retro_vfs_read_t)(struct retro_vfs_file_handle *stream, void *s, uint64_t len);
+
+/* Write data to a file. Returns the number of bytes written, or -1 for error.
+ * Introduced in VFS API v1 */
+typedef int64_t (RETRO_CALLCONV *retro_vfs_write_t)(struct retro_vfs_file_handle *stream, const void *s, uint64_t len);
+
+/* Flush pending writes to file, if using buffered IO. Returns 0 on sucess, or -1 on failure.
+ * Introduced in VFS API v1 */
+typedef int (RETRO_CALLCONV *retro_vfs_flush_t)(struct retro_vfs_file_handle *stream);
+
+/* Delete the specified file. Returns 0 on success, -1 on failure
+ * Introduced in VFS API v1 */
+typedef int (RETRO_CALLCONV *retro_vfs_remove_t)(const char *path);
+
+/* Rename the specified file. Returns 0 on success, -1 on failure
+ * Introduced in VFS API v1 */
+typedef int (RETRO_CALLCONV *retro_vfs_rename_t)(const char *old_path, const char *new_path);
+
+/* Stat the specified file. Retruns a bitmask of RETRO_VFS_STAT_* flags, none are set if path was not valid.
+ * Additionally stores file size in given variable, unless NULL is given.
+ * Introduced in VFS API v3 */
+typedef int (RETRO_CALLCONV *retro_vfs_stat_t)(const char *path, int32_t *size);
+
+/* Create the specified directory. Returns 0 on success, -1 on unknown failure, -2 if already exists.
+ * Introduced in VFS API v3 */
+typedef int (RETRO_CALLCONV *retro_vfs_mkdir_t)(const char *dir);
+
+/* Open the specified directory for listing. Returns the opaque dir handle, or NULL for error.
+ * Support for the include_hidden argument may vary depending on the platform.
+ * Introduced in VFS API v3 */
+typedef struct retro_vfs_dir_handle *(RETRO_CALLCONV *retro_vfs_opendir_t)(const char *dir, bool include_hidden);
+
+/* Read the directory entry at the current position, and move the read pointer to the next position.
+ * Returns true on success, false if already on the last entry.
+ * Introduced in VFS API v3 */
+typedef bool (RETRO_CALLCONV *retro_vfs_readdir_t)(struct retro_vfs_dir_handle *dirstream);
+
+/* Get the name of the last entry read. Returns a string on success, or NULL for error.
+ * The returned string pointer is valid until the next call to readdir or closedir.
+ * Introduced in VFS API v3 */
+typedef const char *(RETRO_CALLCONV *retro_vfs_dirent_get_name_t)(struct retro_vfs_dir_handle *dirstream);
+
+/* Check if the last entry read was a directory. Returns true if it was, false otherwise (or on error).
+ * Introduced in VFS API v3 */
+typedef bool (RETRO_CALLCONV *retro_vfs_dirent_is_dir_t)(struct retro_vfs_dir_handle *dirstream);
+
+/* Close the directory and release its resources. Must be called if opendir returns non-NULL. Returns 0 on success, -1 on failure.
+ * Whether the call succeeds ot not, the handle passed as parameter becomes invalid and should no longer be used.
+ * Introduced in VFS API v3 */
+typedef int (RETRO_CALLCONV *retro_vfs_closedir_t)(struct retro_vfs_dir_handle *dirstream);
+
+struct retro_vfs_interface
+{
+ /* VFS API v1 */
+ retro_vfs_get_path_t get_path;
+ retro_vfs_open_t open;
+ retro_vfs_close_t close;
+ retro_vfs_size_t size;
+ retro_vfs_tell_t tell;
+ retro_vfs_seek_t seek;
+ retro_vfs_read_t read;
+ retro_vfs_write_t write;
+ retro_vfs_flush_t flush;
+ retro_vfs_remove_t remove;
+ retro_vfs_rename_t rename;
+ /* VFS API v2 */
+ retro_vfs_truncate_t truncate;
+ /* VFS API v3 */
+ retro_vfs_stat_t stat;
+ retro_vfs_mkdir_t mkdir;
+ retro_vfs_opendir_t opendir;
+ retro_vfs_readdir_t readdir;
+ retro_vfs_dirent_get_name_t dirent_get_name;
+ retro_vfs_dirent_is_dir_t dirent_is_dir;
+ retro_vfs_closedir_t closedir;
+};
+
+struct retro_vfs_interface_info
+{
+ /* Set by core: should this be higher than the version the front end supports,
+ * front end will return false in the RETRO_ENVIRONMENT_GET_VFS_INTERFACE call
+ * Introduced in VFS API v1 */
+ uint32_t required_interface_version;
+
+ /* Frontend writes interface pointer here. The frontend also sets the actual
+ * version, must be at least required_interface_version.
+ * Introduced in VFS API v1 */
+ struct retro_vfs_interface *iface;
+};
+
+enum retro_hw_render_interface_type
+{
+ RETRO_HW_RENDER_INTERFACE_VULKAN = 0,
+ RETRO_HW_RENDER_INTERFACE_D3D9 = 1,
+ RETRO_HW_RENDER_INTERFACE_D3D10 = 2,
+ RETRO_HW_RENDER_INTERFACE_D3D11 = 3,
+ RETRO_HW_RENDER_INTERFACE_D3D12 = 4,
+ RETRO_HW_RENDER_INTERFACE_GSKIT_PS2 = 5,
+ RETRO_HW_RENDER_INTERFACE_DUMMY = INT_MAX
+};
+
+/* Base struct. All retro_hw_render_interface_* types
+ * contain at least these fields. */
+struct retro_hw_render_interface
+{
+ enum retro_hw_render_interface_type interface_type;
+ unsigned interface_version;
+};
+
+typedef void (RETRO_CALLCONV *retro_set_led_state_t)(int led, int state);
+struct retro_led_interface
+{
+ retro_set_led_state_t set_led_state;
+};
+
+/* Retrieves the current state of the MIDI input.
+ * Returns true if it's enabled, false otherwise. */
+typedef bool (RETRO_CALLCONV *retro_midi_input_enabled_t)(void);
+
+/* Retrieves the current state of the MIDI output.
+ * Returns true if it's enabled, false otherwise */
+typedef bool (RETRO_CALLCONV *retro_midi_output_enabled_t)(void);
+
+/* Reads next byte from the input stream.
+ * Returns true if byte is read, false otherwise. */
+typedef bool (RETRO_CALLCONV *retro_midi_read_t)(uint8_t *byte);
+
+/* Writes byte to the output stream.
+ * 'delta_time' is in microseconds and represent time elapsed since previous write.
+ * Returns true if byte is written, false otherwise. */
+typedef bool (RETRO_CALLCONV *retro_midi_write_t)(uint8_t byte, uint32_t delta_time);
+
+/* Flushes previously written data.
+ * Returns true if successful, false otherwise. */
+typedef bool (RETRO_CALLCONV *retro_midi_flush_t)(void);
+
+struct retro_midi_interface
+{
+ retro_midi_input_enabled_t input_enabled;
+ retro_midi_output_enabled_t output_enabled;
+ retro_midi_read_t read;
+ retro_midi_write_t write;
+ retro_midi_flush_t flush;
+};
+
+enum retro_hw_render_context_negotiation_interface_type
+{
+ RETRO_HW_RENDER_CONTEXT_NEGOTIATION_INTERFACE_VULKAN = 0,
+ RETRO_HW_RENDER_CONTEXT_NEGOTIATION_INTERFACE_DUMMY = INT_MAX
+};
+
+/* Base struct. All retro_hw_render_context_negotiation_interface_* types
+ * contain at least these fields. */
+struct retro_hw_render_context_negotiation_interface
+{
+ enum retro_hw_render_context_negotiation_interface_type interface_type;
+ unsigned interface_version;
+};
+
+/* Serialized state is incomplete in some way. Set if serialization is
+ * usable in typical end-user cases but should not be relied upon to
+ * implement frame-sensitive frontend features such as netplay or
+ * rerecording. */
+#define RETRO_SERIALIZATION_QUIRK_INCOMPLETE (1 << 0)
+/* The core must spend some time initializing before serialization is
+ * supported. retro_serialize() will initially fail; retro_unserialize()
+ * and retro_serialize_size() may or may not work correctly either. */
+#define RETRO_SERIALIZATION_QUIRK_MUST_INITIALIZE (1 << 1)
+/* Serialization size may change within a session. */
+#define RETRO_SERIALIZATION_QUIRK_CORE_VARIABLE_SIZE (1 << 2)
+/* Set by the frontend to acknowledge that it supports variable-sized
+ * states. */
+#define RETRO_SERIALIZATION_QUIRK_FRONT_VARIABLE_SIZE (1 << 3)
+/* Serialized state can only be loaded during the same session. */
+#define RETRO_SERIALIZATION_QUIRK_SINGLE_SESSION (1 << 4)
+/* Serialized state cannot be loaded on an architecture with a different
+ * endianness from the one it was saved on. */
+#define RETRO_SERIALIZATION_QUIRK_ENDIAN_DEPENDENT (1 << 5)
+/* Serialized state cannot be loaded on a different platform from the one it
+ * was saved on for reasons other than endianness, such as word size
+ * dependence */
+#define RETRO_SERIALIZATION_QUIRK_PLATFORM_DEPENDENT (1 << 6)
+
+#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_SYSTEM_RAM (1 << 2) /* The memory area is system RAM. This is main RAM of the gaming system. */
+#define RETRO_MEMDESC_SAVE_RAM (1 << 3) /* The memory area is save RAM. This RAM is usually found on a game cartridge, backed up by a battery. */
+#define RETRO_MEMDESC_VIDEO_RAM (1 << 4) /* The memory area is video RAM (VRAM) */
+#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
+ * 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
+ * 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
+ * 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
+ * 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
+ /* 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
+ * 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.
+ * 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
+ /* 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
+ * 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
+ * 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
+ /* 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_-,
+ * 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
+ * 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
+ * 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.
@@ -928,27 +1450,58 @@ struct retro_memory_descriptor
* '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
+ * '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;
+
+ /* TODO: When finalizing this one, add a description field, which should be
+ * "WRAM" or something roughly equally long. */
+
+ /* TODO: When finalizing this one, replace 'select' with 'limit', which tells
+ * which bits can vary and still refer to the same address (limit = ~select).
+ * TODO: limit? range? vary? something else? */
+
+ /* TODO: When finalizing this one, if 'len' is above what 'select' (or
+ * 'limit') allows, it's bankswitched. Bankswitched data must have both 'len'
+ * and 'select' != 0, and the mappings don't tell how the system switches the
+ * banks. */
+
+ /* TODO: When finalizing this one, fix the 'len' bit removal order.
+ * For len=0x1800, pointer 0x1C00 should go to 0x1400, not 0x0C00.
+ * Algorithm: Take bits highest to lowest, but if it goes above len, clear
+ * the most recent addition and continue on the next bit.
+ * TODO: Can the above be optimized? Is "remove the lowest bit set in both
+ * pointer and 'len'" equivalent? */
+
+ /* TODO: Some emulators (MAME?) emulate big endian systems by only accessing
+ * the emulated memory in 32-bit chunks, native endian. But that's nothing
+ * compared to Darek Mihocka <http://www.emulators.com/docs/nx07_vm101.htm>
+ * (section Emulation 103 - Nearly Free Byte Reversal) - he flips the ENTIRE
+ * RAM backwards! I'll want to represent both of those, via some flags.
+ *
+ * I suspect MAME either didn't think of that idea, or don't want the #ifdef.
+ * Not sure which, nor do I really care. */
+
+ /* TODO: Some of those flags are unused and/or don't really make sense. Clean
+ * them up. */
};
-/* The frontend may use the largest value of 'start'+'select' in a
+/* 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
+ * 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
+ * (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
@@ -957,7 +1510,7 @@ struct retro_memory_descriptor
* .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
+ * (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
@@ -983,13 +1536,13 @@ struct retro_memory_map
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
+ /* 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
+ /* 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). */
@@ -1007,8 +1560,8 @@ 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
+ /* The memory type for retro_get_memory(). This should be at
+ * least 0x100 to avoid conflict with standardized
* libretro memory types. */
unsigned type;
};
@@ -1027,11 +1580,11 @@ struct retro_subsystem_rom_info
/* Same definition as retro_get_system_info(). */
bool block_extract;
- /* This is set if the content is required to load a game.
+ /* 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
+ /* Content can have multiple associated persistent
* memory types (retro_get_memory()). */
const struct retro_subsystem_memory_info *memory;
unsigned num_memory;
@@ -1049,38 +1602,38 @@ struct retro_subsystem_info
*/
const char *ident;
- /* Infos for each content file. The first entry is assumed to be the
+ /* 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,
+ * 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
+ * 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);
+typedef void (RETRO_CALLCONV *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
+ * Cores should only return symbols which are actual
* extensions to the libretro API.
*
- * Frontends should not use this to obtain symbols to standard
+ * 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,
+ * 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);
+typedef retro_proc_address_t (RETRO_CALLCONV *retro_get_proc_address_t)(const char *sym);
struct retro_get_proc_address_interface
{
@@ -1098,7 +1651,7 @@ enum retro_log_level
};
/* Logging function. Takes log level argument as well. */
-typedef void (*retro_log_printf_t)(enum retro_log_level level,
+typedef void (RETRO_CALLCONV *retro_log_printf_t)(enum retro_log_level level,
const char *fmt, ...);
struct retro_log_callback
@@ -1125,6 +1678,12 @@ struct retro_log_callback
#define RETRO_SIMD_VFPU (1 << 13)
#define RETRO_SIMD_PS (1 << 14)
#define RETRO_SIMD_AES (1 << 15)
+#define RETRO_SIMD_VFPV3 (1 << 16)
+#define RETRO_SIMD_VFPV4 (1 << 17)
+#define RETRO_SIMD_POPCNT (1 << 18)
+#define RETRO_SIMD_MOVBE (1 << 19)
+#define RETRO_SIMD_CMOV (1 << 20)
+#define RETRO_SIMD_ASIMD (1 << 21)
typedef uint64_t retro_perf_tick_t;
typedef int64_t retro_time_t;
@@ -1142,34 +1701,34 @@ struct retro_perf_counter
/* Returns current time in microseconds.
* Tries to use the most accurate timer available.
*/
-typedef retro_time_t (*retro_perf_get_time_usec_t)(void);
+typedef retro_time_t (RETRO_CALLCONV *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
+ * 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);
+typedef retro_perf_tick_t (RETRO_CALLCONV *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);
+typedef uint64_t (RETRO_CALLCONV *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);
+typedef void (RETRO_CALLCONV *retro_perf_log_t)(void);
/* Register a performance counter.
- * ident field must be set with a discrete value and other values in
+ * 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
+ * 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);
+typedef void (RETRO_CALLCONV *retro_perf_register_t)(struct retro_perf_counter *counter);
/* Starts a registered counter. */
-typedef void (*retro_perf_start_t)(struct retro_perf_counter *counter);
+typedef void (RETRO_CALLCONV *retro_perf_start_t)(struct retro_perf_counter *counter);
/* Stops a registered counter. */
-typedef void (*retro_perf_stop_t)(struct retro_perf_counter *counter);
+typedef void (RETRO_CALLCONV *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.:
@@ -1232,10 +1791,10 @@ enum retro_sensor_action
#define RETRO_SENSOR_ACCELEROMETER_Y 1
#define RETRO_SENSOR_ACCELEROMETER_Z 2
-typedef bool (*retro_set_sensor_state_t)(unsigned port,
+typedef bool (RETRO_CALLCONV *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);
+typedef float (RETRO_CALLCONV *retro_sensor_get_input_t)(unsigned port, unsigned id);
struct retro_sensor_interface
{
@@ -1252,76 +1811,80 @@ enum retro_camera_buffer
};
/* Starts the camera driver. Can only be called in retro_run(). */
-typedef bool (*retro_camera_start_t)(void);
+typedef bool (RETRO_CALLCONV *retro_camera_start_t)(void);
/* Stops the camera driver. Can only be called in retro_run(). */
-typedef void (*retro_camera_stop_t)(void);
+typedef void (RETRO_CALLCONV *retro_camera_stop_t)(void);
-/* Callback which signals when the camera driver is initialized
+/* 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);
+typedef void (RETRO_CALLCONV *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,
+typedef void (RETRO_CALLCONV *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
+ * 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
+ * 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
+ * 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
+ * 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
+ * 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,
+typedef void (RETRO_CALLCONV *retro_camera_frame_opengl_texture_t)(unsigned texture_id,
unsigned texture_target, const float *affine);
struct retro_camera_callback
{
- /* Set by libretro core.
+ /* Set by libretro core.
* Example bitmask: caps = (1 << RETRO_CAMERA_BUFFER_OPENGL_TEXTURE) | (1 << RETRO_CAMERA_BUFFER_RAW_FRAMEBUFFER).
*/
- uint64_t caps;
+ uint64_t caps;
- unsigned width; /* Desired resolution for camera. Is only used as a hint. */
+ /* Desired resolution for camera. Is only used as a hint. */
+ unsigned width;
unsigned height;
- retro_camera_start_t start; /* Set by frontend. */
- retro_camera_stop_t stop; /* Set by frontend. */
+
+ /* Set by frontend. */
+ retro_camera_start_t start;
+ retro_camera_stop_t stop;
/* 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;
+ retro_camera_frame_opengl_texture_t frame_opengl_texture;
- /* Set by libretro core. Called after camera driver is initialized and
+ /* 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
+ /* 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
+/* Sets the interval of time and/or distance at which to update/poll
* location-based data.
*
* To ensure compatibility with all location-based implementations,
@@ -1330,28 +1893,28 @@ struct retro_camera_callback
* 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,
+typedef void (RETRO_CALLCONV *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
+ * current location at regular intervals (which are defined with
* retro_location_set_interval_t). */
-typedef bool (*retro_location_start_t)(void);
+typedef bool (RETRO_CALLCONV *retro_location_start_t)(void);
-/* Stop location services. The device will stop listening for changes
+/* Stop location services. The device will stop listening for changes
* to the current location. */
-typedef void (*retro_location_stop_t)(void);
+typedef void (RETRO_CALLCONV *retro_location_stop_t)(void);
-/* Get the position of the current location. Will set parameters to
+/* 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,
+typedef bool (RETRO_CALLCONV *retro_location_get_position_t)(double *lat, double *lon,
double *horiz_accuracy, double *vert_accuracy);
-/* Callback which signals when the location driver is initialized
+/* 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);
+typedef void (RETRO_CALLCONV *retro_location_lifetime_status_t)(void);
struct retro_location_callback
{
@@ -1372,14 +1935,14 @@ enum retro_rumble_effect
RETRO_RUMBLE_DUMMY = INT_MAX
};
-/* Sets rumble state for joypad plugged in port 'port'.
+/* 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.
+ * 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,
+typedef bool (RETRO_CALLCONV *retro_set_rumble_state_t)(unsigned port,
enum retro_rumble_effect effect, uint16_t strength);
struct retro_rumble_interface
@@ -1388,16 +1951,16 @@ struct retro_rumble_interface
};
/* Notifies libretro that audio data should be written. */
-typedef void (*retro_audio_callback_t)(void);
+typedef void (RETRO_CALLCONV *retro_audio_callback_t)(void);
-/* True: Audio driver in frontend is active, and callback is
+/* 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
+ * 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);
+typedef void (RETRO_CALLCONV *retro_audio_set_state_callback_t)(bool enabled);
struct retro_audio_callback
{
@@ -1405,21 +1968,21 @@ struct retro_audio_callback
retro_audio_set_state_callback_t set_state;
};
-/* Notifies a libretro core of time spent since last invocation
+/* 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
+ * 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);
+typedef void (RETRO_CALLCONV *retro_frame_time_callback_t)(retro_usec_t usec);
struct retro_frame_time_callback
{
retro_frame_time_callback_t callback;
- /* Represents the time of one frame. It is computed as
- * 1000000 / fps, but the implementation will resolve the
+ /* 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;
};
@@ -1435,24 +1998,24 @@ struct retro_frame_time_callback
* 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,
+ * Also called first time video driver is initialized,
* allowing libretro core to initialize resources.
*/
-typedef void (*retro_hw_context_reset_t)(void);
+typedef void (RETRO_CALLCONV *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);
+typedef uintptr_t (RETRO_CALLCONV *retro_hw_get_current_framebuffer_t)(void);
/* Get a symbol from HW context. */
-typedef retro_proc_address_t (*retro_hw_get_proc_address_t)(const char *sym);
+typedef retro_proc_address_t (RETRO_CALLCONV *retro_hw_get_proc_address_t)(const char *sym);
enum retro_hw_context_type
{
RETRO_HW_CONTEXT_NONE = 0,
/* OpenGL 2.x. Driver can choose to use latest compatibility context. */
- RETRO_HW_CONTEXT_OPENGL = 1,
+ RETRO_HW_CONTEXT_OPENGL = 1,
/* OpenGL ES 2.0. */
RETRO_HW_CONTEXT_OPENGLES2 = 2,
/* Modern desktop core GL context. Use version_major/
@@ -1464,6 +2027,13 @@ enum retro_hw_context_type
* use the corresponding enums directly. */
RETRO_HW_CONTEXT_OPENGLES_VERSION = 5,
+ /* Vulkan, see RETRO_ENVIRONMENT_GET_HW_RENDER_INTERFACE. */
+ RETRO_HW_CONTEXT_VULKAN = 6,
+
+ /* Direct3D, set version_major to select the type of interface
+ * returned by RETRO_ENVIRONMENT_GET_HW_RENDER_INTERFACE */
+ RETRO_HW_CONTEXT_DIRECT3D = 7,
+
RETRO_HW_CONTEXT_DUMMY = INT_MAX
};
@@ -1475,10 +2045,10 @@ struct retro_hw_render_callback
/* 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
+ * 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
+ * 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
@@ -1486,58 +2056,65 @@ struct retro_hw_render_callback
*/
retro_hw_context_reset_t context_reset;
- /* Set by frontend. */
+ /* Set by frontend.
+ * TODO: This is rather obsolete. The frontend should not
+ * be providing preallocated framebuffers. */
retro_hw_get_current_framebuffer_t get_current_framebuffer;
- /* Set by frontend. */
+ /* Set by frontend.
+ * Can return all relevant functions, including glClear on Windows. */
retro_hw_get_proc_address_t get_proc_address;
- /* Set if render buffers should have depth component attached. */
+ /* Set if render buffers should have depth component attached.
+ * TODO: Obsolete. */
bool depth;
- /* Set if stencil buffers should be attached. */
+ /* Set if stencil buffers should be attached.
+ * TODO: Obsolete. */
bool stencil;
- /* If depth and stencil are true, a packed 24/8 buffer will be added.
+ /* 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. */
+ /* Use conventional bottom-left origin convention. If false,
+ * standard libretro top-left origin semantics are used.
+ * TODO: Move to GL specific interface. */
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
+ /* If this is true, the frontend will go very far to avoid
* resetting context in scenarios like toggling fullscreen, etc.
+ * TODO: Obsolete? Maybe frontend should just always assume this ...
*/
bool cache_context;
- /* The reset callback might still be called in extreme situations
+ /* 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
+ * 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
+
+ /* 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
+ * 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
+ * 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
+ * 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
+ * and the libretro implementation must not try to free any OpenGL
* resources in the subsequent context_reset.
*/
@@ -1545,7 +2122,7 @@ struct retro_hw_render_callback
bool debug_context;
};
-/* Callback type passed in RETRO_ENVIRONMENT_SET_KEYBOARD_CALLBACK.
+/* 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.
@@ -1553,16 +2130,16 @@ struct retro_hw_render_callback
* 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
+ * 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
+ * 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,
+typedef void (RETRO_CALLCONV *retro_keyboard_event_t)(bool down, unsigned keycode,
uint32_t character, uint16_t key_modifiers);
struct retro_keyboard_callback
@@ -1571,39 +2148,39 @@ struct retro_keyboard_callback
};
/* Callbacks for RETRO_ENVIRONMENT_SET_DISK_CONTROL_INTERFACE.
- * Should be set for implementations which can swap out multiple disk
+ * 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
+ * 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
+ * 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.
*/
-typedef bool (*retro_set_eject_state_t)(bool ejected);
+typedef bool (RETRO_CALLCONV *retro_set_eject_state_t)(bool ejected);
/* Gets current eject state. The initial state is 'not ejected'. */
-typedef bool (*retro_get_eject_state_t)(void);
+typedef bool (RETRO_CALLCONV *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.
*/
-typedef unsigned (*retro_get_image_index_t)(void);
+typedef unsigned (RETRO_CALLCONV *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
+ * The implementation supports setting "no disk" by using an
* index >= get_num_images().
*/
-typedef bool (*retro_set_image_index_t)(unsigned index);
+typedef bool (RETRO_CALLCONV *retro_set_image_index_t)(unsigned index);
/* Gets total number of images which are available to use. */
-typedef unsigned (*retro_get_num_images_t)(void);
+typedef unsigned (RETRO_CALLCONV *retro_get_num_images_t)(void);
struct retro_game_info;
@@ -1611,22 +2188,22 @@ struct retro_game_info;
* 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
+ * 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()
+ * 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,
+typedef bool (RETRO_CALLCONV *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
+ * 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);
+typedef bool (RETRO_CALLCONV *retro_add_image_index_t)(void);
struct retro_disk_control_callback
{
@@ -1655,7 +2232,7 @@ enum retro_pixel_format
/* 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
+ * 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. */
@@ -1685,43 +2262,52 @@ struct retro_input_descriptor
/* Human readable description for parameters.
* The pointer must remain valid until
* retro_unload_game() is called. */
- const char *description;
+ const char *description;
};
struct retro_system_info
{
- /* All pointers are owned by libretro implementation, and pointers must
+ /* 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
+ 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
+ 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
+ * 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.
+ /* Libretro cores that need to have direct access to their content
+ * files, including cores which use the path of the content files to
+ * determine the paths of other files, should set need_fullpath to true.
+ *
+ * Cores should strive for setting need_fullpath to false,
+ * as it allows the frontend to perform patching, etc.
+ *
+ * If need_fullpath is true and retro_load_game() is called:
+ * - retro_game_info::path is guaranteed to have a valid path
+ * - retro_game_info::data and retro_game_info::size are invalid
*
- * If false, ::data and ::size are guaranteed to be valid, but ::path
- * might not be valid.
+ * If need_fullpath is false and retro_load_game() is called:
+ * - retro_game_info::path may be NULL
+ * - retro_game_info::data and retro_game_info::size are guaranteed
+ * to 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;
+ * See also:
+ * - RETRO_ENVIRONMENT_GET_SYSTEM_DIRECTORY
+ * - RETRO_ENVIRONMENT_GET_SAVE_DIRECTORY
+ */
+ bool need_fullpath;
- /* If true, the frontend is not allowed to extract any archives before
+ /* If true, the frontend is not allowed to extract any archives before
* loading the real content.
- * Necessary for certain libretro implementations that load games
+ * Necessary for certain libretro implementations that load games
* from zipped archives. */
- bool block_extract;
+ bool block_extract;
};
struct retro_game_geometry
@@ -1753,14 +2339,14 @@ struct retro_system_av_info
struct retro_variable
{
/* Variable to query in RETRO_ENVIRONMENT_GET_VARIABLE.
- * If NULL, obtains the complete environment string if more
+ * If NULL, obtains the complete environment string if more
* complex parsing is necessary.
- * The environment string is formatted as key-value pairs
+ * 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;
};
@@ -1768,42 +2354,74 @@ struct retro_variable
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
+ * Sometimes used as a reference for building other paths.
+ * May be NULL if game was loaded from stdin or similar,
+ * but in this case some cores will be unable to load `data`.
+ * So, it is preferable to fabricate something here instead
+ * of passing NULL, which will help more cores to succeed.
+ * retro_system_info::need_fullpath requires
* that this path is valid. */
- const void *data; /* Memory buffer of loaded game. Will be NULL
+ 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. */
};
+#define RETRO_MEMORY_ACCESS_WRITE (1 << 0)
+ /* The core will write to the buffer provided by retro_framebuffer::data. */
+#define RETRO_MEMORY_ACCESS_READ (1 << 1)
+ /* The core will read from retro_framebuffer::data. */
+#define RETRO_MEMORY_TYPE_CACHED (1 << 0)
+ /* The memory in data is cached.
+ * If not cached, random writes and/or reading from the buffer is expected to be very slow. */
+struct retro_framebuffer
+{
+ void *data; /* The framebuffer which the core can render into.
+ Set by frontend in GET_CURRENT_SOFTWARE_FRAMEBUFFER.
+ The initial contents of data are unspecified. */
+ unsigned width; /* The framebuffer width used by the core. Set by core. */
+ unsigned height; /* The framebuffer height used by the core. Set by core. */
+ size_t pitch; /* The number of bytes between the beginning of a scanline,
+ and beginning of the next scanline.
+ Set by frontend in GET_CURRENT_SOFTWARE_FRAMEBUFFER. */
+ enum retro_pixel_format format; /* The pixel format the core must use to render into data.
+ This format could differ from the format used in
+ SET_PIXEL_FORMAT.
+ Set by frontend in GET_CURRENT_SOFTWARE_FRAMEBUFFER. */
+
+ unsigned access_flags; /* How the core will access the memory in the framebuffer.
+ RETRO_MEMORY_ACCESS_* flags.
+ Set by core. */
+ unsigned memory_flags; /* Flags telling core how the memory has been mapped.
+ RETRO_MEMORY_TYPE_* flags.
+ Set by frontend in GET_CURRENT_SOFTWARE_FRAMEBUFFER. */
+};
+
/* Callbacks */
-/* Environment callback. Gives implementations a way of performing
+/* Environment callback. Gives implementations a way of performing
* uncommon tasks. Extensible. */
-typedef bool (*retro_environment_t)(unsigned cmd, void *data);
+typedef bool (RETRO_CALLCONV *retro_environment_t)(unsigned cmd, void *data);
-/* Render a frame. Pixel format is 15-bit 0RGB1555 native endian
+/* 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
+ * 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
+ * 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,
+typedef void (RETRO_CALLCONV *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
+/* 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);
+typedef void (RETRO_CALLCONV *retro_audio_sample_t)(int16_t left, int16_t right);
/* Renders multiple audio frames in one go.
*
@@ -1811,113 +2429,121 @@ typedef void (*retro_audio_sample_t)(int16_t left, int16_t right);
* 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,
+typedef size_t (RETRO_CALLCONV *retro_audio_sample_batch_t)(const int16_t *data,
size_t frames);
/* Polls input. */
-typedef void (*retro_input_poll_t)(void);
+typedef void (RETRO_CALLCONV *retro_input_poll_t)(void);
-/* Queries for input for player 'port'. device will be masked with
+/* Queries for input for player 'port'. device will be masked with
* RETRO_DEVICE_MASK.
*
- * Specialization of devices such as RETRO_DEVICE_JOYPAD_MULTITAP that
+ * 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,
+typedef int16_t (RETRO_CALLCONV *retro_input_state_t)(unsigned port, unsigned device,
unsigned index, unsigned id);
-/* Sets callbacks. retro_set_environment() is guaranteed to be called
+/* 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
+ * 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);
-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);
+RETRO_API void retro_set_environment(retro_environment_t);
+RETRO_API void retro_set_video_refresh(retro_video_refresh_t);
+RETRO_API void retro_set_audio_sample(retro_audio_sample_t);
+RETRO_API void retro_set_audio_sample_batch(retro_audio_sample_batch_t);
+RETRO_API void retro_set_input_poll(retro_input_poll_t);
+RETRO_API void retro_set_input_state(retro_input_state_t);
/* Library global initialization/deinitialization. */
-void retro_init(void);
-void retro_deinit(void);
+RETRO_API void retro_init(void);
+RETRO_API void retro_deinit(void);
/* Must return RETRO_API_VERSION. Used to validate ABI compatibility
* when the API is revised. */
-unsigned retro_api_version(void);
+RETRO_API unsigned retro_api_version(void);
-/* Gets statically known system info. Pointers provided in *info
+/* 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);
+RETRO_API 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
+ * 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
+ * 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);
+RETRO_API void retro_get_system_av_info(struct retro_system_av_info *info);
/* Sets device to be used for player 'port'.
- * By default, RETRO_DEVICE_JOYPAD is assumed to be plugged into all
+ * 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);
+ * 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.
+ *
+ * As part of the core's implementation of retro_set_controller_port_device,
+ * the core should call RETRO_ENVIRONMENT_SET_INPUT_DESCRIPTORS to notify the
+ * frontend if the descriptions for any controls have changed as a
+ * result of changing the device type.
+ */
+RETRO_API void retro_set_controller_port_device(unsigned port, unsigned device);
/* Resets the current game. */
-void retro_reset(void);
+RETRO_API 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
+ * 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);
+RETRO_API void retro_run(void);
-/* Returns the amount of data the implementation requires to serialize
+/* 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
+ * 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);
+RETRO_API 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. */
-bool retro_serialize(void *data, size_t size);
-bool retro_unserialize(const void *data, size_t size);
+RETRO_API bool retro_serialize(void *data, size_t size);
+RETRO_API 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);
+RETRO_API void retro_cheat_reset(void);
+RETRO_API void retro_cheat_set(unsigned index, bool enabled, const char *code);
-/* Loads a game. */
-bool retro_load_game(const struct retro_game_info *game);
+/* Loads a game.
+ * Return true to indicate successful loading and false to indicate load failure.
+ */
+RETRO_API bool retro_load_game(const struct retro_game_info *game);
/* Loads a "special" kind of game. Should not be used,
* except in extreme cases. */
-bool retro_load_game_special(
+RETRO_API bool retro_load_game_special(
unsigned game_type,
const struct retro_game_info *info, size_t num_info
);
-/* Unloads a currently loaded game. */
-void retro_unload_game(void);
+/* Unloads the currently loaded game. Called before retro_deinit(void). */
+RETRO_API void retro_unload_game(void);
/* Gets region of game. */
-unsigned retro_get_region(void);
+RETRO_API unsigned retro_get_region(void);
/* Gets region of memory. */
-void *retro_get_memory_data(unsigned id);
-size_t retro_get_memory_size(unsigned id);
+RETRO_API void *retro_get_memory_data(unsigned id);
+RETRO_API size_t retro_get_memory_size(unsigned id);
#ifdef __cplusplus
}
diff --git a/frontend/link.T b/frontend/link.T
new file mode 100644
index 0000000..b0c262d
--- /dev/null
+++ b/frontend/link.T
@@ -0,0 +1,5 @@
+{
+ global: retro_*;
+ local: *;
+};
+
diff --git a/frontend/main.c b/frontend/main.c
index 43a5548..860dec0 100644
--- a/frontend/main.c
+++ b/frontend/main.c
@@ -11,7 +11,7 @@
#include <unistd.h>
#include <signal.h>
#include <time.h>
-#ifndef _WIN32
+#if !defined(_WIN32) && !defined(NO_DYLIB)
#include <dlfcn.h>
#endif
@@ -152,8 +152,8 @@ void emu_set_default_config(void)
new_dynarec_hacks = 0;
cycle_multiplier = 200;
- in_type1 = PSE_PAD_TYPE_STANDARD;
- in_type2 = PSE_PAD_TYPE_STANDARD;
+ in_type[0] = PSE_PAD_TYPE_STANDARD;
+ in_type[1] = PSE_PAD_TYPE_STANDARD;
}
void do_emu_action(void)
@@ -722,10 +722,10 @@ void SysReset() {
// reset can run code, timing must be set
pl_timing_prepare(Config.PsxType);
- EmuReset();
-
- // hmh core forgets this
+ // hmh core forgets this
CDR_stop();
+
+ EmuReset();
GPU_updateLace = real_lace;
g_emu_resetting = 0;
@@ -773,7 +773,7 @@ int emu_save_state(int slot)
return ret;
ret = SaveState(fname);
-#ifdef HAVE_PRE_ARMV7 /* XXX GPH hack */
+#if defined(HAVE_PRE_ARMV7) && !defined(_3DS) /* XXX GPH hack */
sync();
#endif
SysPrintf("* %s \"%s\" [%d]\n",
@@ -987,7 +987,7 @@ void *SysLoadLibrary(const char *lib) {
return (void *)(long)(PLUGIN_DL_BASE + builtin_plugin_ids[i]);
}
-#ifndef _WIN32
+#if !defined(_WIN32) && !defined(NO_DYLIB)
ret = dlopen(lib, RTLD_NOW);
if (ret == NULL)
SysMessage("dlopen: %s", dlerror());
@@ -1004,7 +1004,7 @@ void *SysLoadSym(void *lib, const char *sym) {
if (PLUGIN_DL_BASE <= plugid && plugid < PLUGIN_DL_BASE + ARRAY_SIZE(builtin_plugins))
return plugin_link(plugid - PLUGIN_DL_BASE, sym);
-#ifndef _WIN32
+#if !defined(_WIN32) && !defined(NO_DYLIB)
return dlsym(lib, sym);
#else
return NULL;
@@ -1012,7 +1012,9 @@ void *SysLoadSym(void *lib, const char *sym) {
}
const char *SysLibError() {
-#ifndef _WIN32
+#if defined(NO_DYLIB)
+ return NULL;
+#elif !defined(_WIN32)
return dlerror();
#else
return "not supported";
@@ -1025,8 +1027,7 @@ void SysCloseLibrary(void *lib) {
if (PLUGIN_DL_BASE <= plugid && plugid < PLUGIN_DL_BASE + ARRAY_SIZE(builtin_plugins))
return;
-#ifndef _WIN32
+#if !defined(_WIN32) && !defined(NO_DYLIB)
dlclose(lib);
#endif
}
-
diff --git a/frontend/menu.c b/frontend/menu.c
index 0b3f553..babe109 100644
--- a/frontend/menu.c
+++ b/frontend/menu.c
@@ -101,13 +101,10 @@ int scanlines, scanline_level = 20;
int soft_scaling, analog_deadzone; // for Caanoo
int soft_filter;
-#ifndef HAVE_PRE_ARMV7
-#define DEFAULT_PSX_CLOCK 57
-#define DEFAULT_PSX_CLOCK_S "57"
-#else
-#define DEFAULT_PSX_CLOCK 50
-#define DEFAULT_PSX_CLOCK_S "50"
-#endif
+// Default to 100% CPU speed as most hardware can handle it nowadays using the dynamic recompiler.
+// If not, the option is in the advanced speed hacks menu, so in a logical place.
+#define DEFAULT_PSX_CLOCK 100
+#define DEFAULT_PSX_CLOCK_S "100"
static const char *bioses[24];
static const char *gpu_plugins[16];
@@ -309,12 +306,12 @@ static void menu_sync_config(void)
switch (in_type_sel1) {
case 1: in_type1 = PSE_PAD_TYPE_ANALOGPAD; break;
- case 2: in_type1 = PSE_PAD_TYPE_GUNCON; break;
+ case 2: in_type1 = PSE_PAD_TYPE_NEGCON; break;
default: in_type1 = PSE_PAD_TYPE_STANDARD;
}
switch (in_type_sel2) {
case 1: in_type2 = PSE_PAD_TYPE_ANALOGPAD; break;
- case 2: in_type2 = PSE_PAD_TYPE_GUNCON; break;
+ case 2: in_type2 = PSE_PAD_TYPE_NEGCON; break;
default: in_type2 = PSE_PAD_TYPE_STANDARD;
}
if (in_evdev_allow_abs_only != allow_abs_only_old) {
diff --git a/frontend/pandora/pcsx.png b/frontend/pandora/pcsx.png
deleted file mode 100644
index 71f36d0..0000000
--- a/frontend/pandora/pcsx.png
+++ /dev/null
Binary files differ
diff --git a/frontend/pandora/pcsx.pxml.templ b/frontend/pandora/pcsx.pxml.templ
deleted file mode 100644
index f748065..0000000
--- a/frontend/pandora/pcsx.pxml.templ
+++ /dev/null
@@ -1,42 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<PXML xmlns="http://openpandora.org/namespaces/PXML" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="PXML_schema.xsd">
-<package id="package.pcsx_rearmed.notaz">
- <titles>
- <title lang="en_US">PCSX ReARMed</title>
- </titles>
- <version major="1" minor="9" release="93" build="%PR%"/>
- <author name="PCSX team/notaz" website="http://notaz.gp2x.de/"/>
-</package>
-<application id="pcsx_rearmed.notaz.%PR%" appdata="pcsx_rearmed">
- <titles>
- <title lang="en_US">PCSX ReARMed %PR%</title>
- </titles>
- <title lang="en_US">PCSX ReARMed %PR%</title>
-
- <descriptions>
- <description lang="en_US">PCSX ReARMed is heavily optimized PlayStation Emulator. It's a PCSX fork based on the PCSX-Reloaded project, which itself contains code from PCSX, PCSX-df and PCSX-Revolution.
-
-The emulator features MIPS->ARM recompiler by Ari64 and ARM NEON GPU by Exophase, that in many cases produces pixel perfect graphics at very high performance. There is also NEON-optimized GTE code, optimized P.E.Op.S. (Pete's) SPU; PCSX4ALL and traditional P.E.Op.S. GPUs are also available.</description>
- </descriptions>
-
- <exec command="pcsx.sh"/>
-
- <icon src="pcsx.png"/>
-
- <author name="PCSX team/notaz" website="http://notaz.gp2x.de/"/>
-
- <version major="1" minor="9" release="93" build="%PR%"/>
-
- <licenses>
- <license name="GPLv2+" url="http://www.gnu.org/licenses/gpl-2.0.html" sourcecodeurl="http://notaz.gp2x.de/cgi-bin/gitweb.cgi?p=pcsx_rearmed.git"/>
- </licenses>
-
- <info name="PCSX ReARMed %PR% readme" type="text/plain" src="readme.txt"/>
-
- <categories>
- <category name="Game">
- <subcategory name="Emulator"/>
- </category>
- </categories>
-</application>
-</PXML>
diff --git a/frontend/pandora/pcsx.sh b/frontend/pandora/pcsx.sh
deleted file mode 100755
index 710f641..0000000
--- a/frontend/pandora/pcsx.sh
+++ /dev/null
@@ -1,24 +0,0 @@
-#!/bin/sh
-
-# stupid nub mode thing
-nub0mode=`cat /proc/pandora/nub0/mode`
-nub1mode=`cat /proc/pandora/nub1/mode`
-/usr/pandora/scripts/op_nubchange.sh absolute absolute
-
-# 4MB for RAM (2+align) + 2MB for vram (1+overdraw)
-# + 10MB for gpu_neon (8+overdraw) + 8MB LUTs
-# no big deal if this fails, only performance loss
-sudo -n /usr/pandora/scripts/op_hugetlb.sh 24
-
-# C64x DSP for SPU
-sudo -n /usr/pandora/scripts/op_dsp_c64.sh
-
-./pcsx "$@"
-
-# restore stuff if pcsx crashes
-./picorestore
-sudo -n /usr/pandora/scripts/op_lcdrate.sh 60
-sudo -n /usr/pandora/scripts/op_gamma.sh 0
-sudo -n /usr/pandora/scripts/op_hugetlb.sh 0
-
-/usr/pandora/scripts/op_nubchange.sh $nub0mode $nub1mode
diff --git a/frontend/pandora/picorestore.c b/frontend/pandora/picorestore.c
deleted file mode 100644
index 77f5720..0000000
--- a/frontend/pandora/picorestore.c
+++ /dev/null
@@ -1,109 +0,0 @@
-/*
- * picorestore - clean up after an omapfb program crash
- *
- * Copyright (c) Gražvydas "notaz" Ignotas, 2010
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * * Neither the name of the organization nor the
- * names of its contributors may be used to endorse or promote products
- * derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
- * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include <stdio.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <sys/ioctl.h>
-#include <linux/fb.h>
-#include <linux/omapfb.h>
-#include <linux/kd.h>
-
-int main()
-{
- struct fb_var_screeninfo fbvar;
- struct omapfb_plane_info pi;
- struct omapfb_mem_info mi;
- int ret, fbdev, kbdfd;
-
- fbdev = open("/dev/fb0", O_RDWR);
- if (fbdev == -1) {
- perror("open fb0");
- goto end_fb0;
- }
-
- ret = ioctl(fbdev, FBIOGET_VSCREENINFO, &fbvar);
- if (ret == -1) {
- perror("FBIOGET_VSCREENINFO ioctl");
- goto end_fb0;
- }
-
- if (fbvar.yoffset != 0) {
- printf("fixing yoffset.. ");
- fbvar.yoffset = 0;
- ret = ioctl(fbdev, FBIOPAN_DISPLAY, &fbvar);
- if (ret < 0)
- perror("ioctl FBIOPAN_DISPLAY");
- else
- printf("ok\n");
- }
-
-end_fb0:
- if (fbdev >= 0)
- close(fbdev);
-
- fbdev = open("/dev/fb1", O_RDWR);
- if (fbdev == -1) {
- perror("open fb1");
- goto end_fb1;
- }
-
- ret = ioctl(fbdev, OMAPFB_QUERY_PLANE, &pi);
- ret |= ioctl(fbdev, OMAPFB_QUERY_MEM, &mi);
- if (ret != 0)
- perror("QUERY_*");
-
- pi.enabled = 0;
- ret = ioctl(fbdev, OMAPFB_SETUP_PLANE, &pi);
- if (ret != 0)
- perror("SETUP_PLANE");
-
- mi.size = 0;
- ret = ioctl(fbdev, OMAPFB_SETUP_MEM, &mi);
- if (ret != 0)
- perror("SETUP_MEM");
-
-end_fb1:
- if (fbdev >= 0)
- close(fbdev);
-
- kbdfd = open("/dev/tty", O_RDWR);
- if (kbdfd == -1) {
- perror("open /dev/tty");
- return 1;
- }
-
- if (ioctl(kbdfd, KDSETMODE, KD_TEXT) == -1)
- perror("KDSETMODE KD_TEXT");
-
- close(kbdfd);
-
- return 0;
-}
diff --git a/frontend/pandora/skin/background.png b/frontend/pandora/skin/background.png
deleted file mode 100644
index f4b4523..0000000
--- a/frontend/pandora/skin/background.png
+++ /dev/null
Binary files differ
diff --git a/frontend/pandora/skin/font.png b/frontend/pandora/skin/font.png
deleted file mode 100644
index 707a5b4..0000000
--- a/frontend/pandora/skin/font.png
+++ /dev/null
Binary files differ
diff --git a/frontend/pandora/skin/readme.txt b/frontend/pandora/skin/readme.txt
deleted file mode 100644
index dd83963..0000000
--- a/frontend/pandora/skin/readme.txt
+++ /dev/null
@@ -1,8 +0,0 @@
-The skin images can be customized, but there are several limitations:
-
-background.png - must be 320x240 image with 24bit RGB colors.
-font.png - must be 128x160 8bit grayscale image.
-selector.png - must be 8x10 8bit grayscale image.
-
-Font and selector colors can be changed by editing skin.txt.
-
diff --git a/frontend/pandora/skin/selector.png b/frontend/pandora/skin/selector.png
deleted file mode 100644
index a439169..0000000
--- a/frontend/pandora/skin/selector.png
+++ /dev/null
Binary files differ
diff --git a/frontend/pandora/skin/skin.txt b/frontend/pandora/skin/skin.txt
deleted file mode 100644
index 1d6979f..0000000
--- a/frontend/pandora/skin/skin.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-// html-style hex color codes, ex. ff0000 is red, 0000ff is blue, etc.
-text_color=ffffc0
-selection_color=808010
-
diff --git a/frontend/pandora/ui_feat.h b/frontend/pandora/ui_feat.h
deleted file mode 100644
index 3bb808a..0000000
--- a/frontend/pandora/ui_feat.h
+++ /dev/null
@@ -1,16 +0,0 @@
-#ifndef UI_FEATURES_H
-#define UI_FEATURES_H
-
-#define MENU_BIOS_PATH "<SD card>/pandora/appdata/pcsx_rearmed/bios/"
-#define BOOT_MSG "Booting up... (press SPACE for menu)"
-#define MENU_SHOW_VARSCALER 1
-#define MENU_SHOW_VOUTMODE 0
-#define MENU_SHOW_SCALER2 0
-#define MENU_SHOW_NUBS_BTNS 1
-#define MENU_SHOW_VIBRATION 0
-#define MENU_SHOW_DEADZONE 0
-#define MENU_SHOW_MINIMIZE 1
-#define MENU_SHOW_FULLSCREEN 0
-#define MENU_SHOW_VOLUME 0
-
-#endif // UI_FEATURES_H
diff --git a/frontend/plugin.c b/frontend/plugin.c
index d9eb04a..1fcd7be 100644
--- a/frontend/plugin.c
+++ b/frontend/plugin.c
@@ -49,24 +49,43 @@ extern void CALLBACK SPUasync(unsigned int, unsigned int);
extern int CALLBACK SPUplayCDDAchannel(short *, int);
/* PAD */
-static long PADreadPort1(PadDataS *pad)
-{
- pad->controllerType = in_type1;
- pad->buttonStatus = ~in_keystate;
- if (in_type1 == PSE_PAD_TYPE_ANALOGPAD) {
- pad->leftJoyX = in_a1[0];
- pad->leftJoyY = in_a1[1];
- pad->rightJoyX = in_a2[0];
- pad->rightJoyY = in_a2[1];
- }
- return 0;
+static long PADreadPort1(PadDataS *pad) {
+ int pad_index = pad->requestPadIndex;
+ pad->controllerType = in_type[pad_index];
+ pad->buttonStatus = ~in_keystate[pad_index];
+ if (multitap1 == 1)
+ pad->portMultitap = 1;
+ else
+ pad->portMultitap = 0;
+
+ if (in_type[pad_index] == PSE_PAD_TYPE_ANALOGJOY || in_type[pad_index] == PSE_PAD_TYPE_ANALOGPAD || in_type[pad_index] == PSE_PAD_TYPE_NEGCON)
+ {
+ pad->leftJoyX = in_analog_left[pad_index][0];
+ pad->leftJoyY = in_analog_left[pad_index][1];
+ pad->rightJoyX = in_analog_right[pad_index][0];
+ pad->rightJoyY = in_analog_right[pad_index][1];
+ }
+ return 0;
}
-static long PADreadPort2(PadDataS *pad)
-{
- pad->controllerType = in_type2;
- pad->buttonStatus = ~in_keystate >> 16;
- return 0;
+static long PADreadPort2(PadDataS *pad) {
+ int pad_index = pad->requestPadIndex;
+
+ pad->controllerType = in_type[pad_index];
+ pad->buttonStatus = ~in_keystate[pad_index];
+ if (multitap2 == 1)
+ pad->portMultitap = 2;
+ else
+ pad->portMultitap = 0;
+
+ if (in_type[pad_index] == PSE_PAD_TYPE_ANALOGJOY || in_type[pad_index] == PSE_PAD_TYPE_ANALOGPAD || in_type[pad_index] == PSE_PAD_TYPE_NEGCON)
+ {
+ pad->leftJoyX = in_analog_left[pad_index][0];
+ pad->leftJoyY = in_analog_left[pad_index][1];
+ pad->rightJoyX = in_analog_right[pad_index][0];
+ pad->rightJoyY = in_analog_right[pad_index][1];
+ }
+ return 0;
}
/* GPU */
diff --git a/frontend/plugin_lib.c b/frontend/plugin_lib.c
index ab4d415..eee255b 100644
--- a/frontend/plugin_lib.c
+++ b/frontend/plugin_lib.c
@@ -36,11 +36,15 @@
#define HUD_HEIGHT 10
-int in_type1, in_type2;
-int in_a1[2] = { 127, 127 }, in_a2[2] = { 127, 127 };
+int in_type[8];
+int multitap1;
+int multitap2;
+int in_analog_left[8][2] = {{ 127, 127 },{ 127, 127 },{ 127, 127 },{ 127, 127 },{ 127, 127 },{ 127, 127 },{ 127, 127 },{ 127, 127 }};
+int in_analog_right[8][2] = {{ 127, 127 },{ 127, 127 },{ 127, 127 },{ 127, 127 },{ 127, 127 },{ 127, 127 },{ 127, 127 },{ 127, 127 }};
int in_adev[2] = { -1, -1 }, in_adev_axis[2][2] = {{ 0, 1 }, { 0, 1 }};
int in_adev_is_nublike[2];
-int in_keystate, in_state_gun;
+unsigned short in_keystate[8];
+int in_state_gun;
int in_enable_vibration;
void *tsdev;
void *pl_vout_buf;
@@ -560,7 +564,7 @@ static void update_analog_nub_adjust(int *x_, int *y_)
static void update_analogs(void)
{
- int *nubp[2] = { in_a1, in_a2 };
+ int *nubp[2] = { in_analog_left[0], in_analog_right[0] };
int vals[2];
int i, a, v, ret;
@@ -597,7 +601,7 @@ static void update_input(void)
unsigned int emu_act;
in_update(actions);
- if (in_type1 == PSE_PAD_TYPE_ANALOGPAD)
+ if (in_type[0] == PSE_PAD_TYPE_ANALOGJOY || in_type[0] == PSE_PAD_TYPE_ANALOGPAD)
update_analogs();
emu_act = actions[IN_BINDTYPE_EMU];
in_state_gun = (emu_act & SACTION_GUN_MASK) >> SACTION_GUN_TRIGGER;
@@ -611,7 +615,7 @@ static void update_input(void)
}
emu_set_action(emu_act);
- in_keystate = actions[IN_BINDTYPE_PLAYER12];
+ in_keystate[0] = actions[IN_BINDTYPE_PLAYER12];
}
#else /* MAEMO */
extern void update_input(void);
diff --git a/frontend/plugin_lib.h b/frontend/plugin_lib.h
index 4a11002..92e62e9 100644
--- a/frontend/plugin_lib.h
+++ b/frontend/plugin_lib.h
@@ -17,8 +17,14 @@ enum {
DKEY_CROSS,
DKEY_SQUARE,
};
-extern int in_type1, in_type2;
-extern int in_keystate, in_state_gun, in_a1[2], in_a2[2];
+extern int in_state_gun;
+extern int in_type[8];
+extern int multitap1;
+extern int multitap2;
+extern int in_analog_left[8][2];
+extern int in_analog_right[8][2];
+extern unsigned short in_keystate[8];
+
extern int in_adev[2], in_adev_axis[2][2];
extern int in_adev_is_nublike[2];
extern int in_enable_vibration;
@@ -65,6 +71,7 @@ struct rearmed_cbs {
int allow_interlace; // 0 off, 1 on, 2 guess
int enhancement_enable;
int enhancement_no_main;
+ int allow_dithering;
} gpu_neon;
struct {
int iUseDither;
diff --git a/frontend/vita/retro_inline.h b/frontend/vita/retro_inline.h
new file mode 100644
index 0000000..8535d84
--- /dev/null
+++ b/frontend/vita/retro_inline.h
@@ -0,0 +1,39 @@
+/* Copyright (C) 2010-2015 The RetroArch team
+ *
+ * ---------------------------------------------------------------------------------------
+ * The following license statement only applies to this file (retro_inline.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_SDK_INLINE_H
+#define __LIBRETRO_SDK_INLINE_H
+
+#ifndef INLINE
+
+#if !defined(__cplusplus) && defined(_WIN32)
+#define INLINE _inline
+#elif defined(__STDC_VERSION__) && __STDC_VERSION__>=199901L
+#define INLINE inline
+#elif defined(__GNUC__)
+#define INLINE __inline__
+#else
+#define INLINE
+#endif
+
+#endif
+#endif
diff --git a/frontend/vita/sys/mman.h b/frontend/vita/sys/mman.h
new file mode 100644
index 0000000..89da513
--- /dev/null
+++ b/frontend/vita/sys/mman.h
@@ -0,0 +1,69 @@
+#ifndef MMAN_H
+#define MMAN_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "stdlib.h"
+#include "stdio.h"
+
+#define PROT_READ 0b001
+#define PROT_WRITE 0b010
+#define PROT_EXEC 0b100
+#define MAP_PRIVATE 2
+#define MAP_ANONYMOUS 0x20
+
+#define MAP_FAILED ((void *)-1)
+
+static inline void* mmap(void *addr, size_t len, int prot, int flags, int fd, off_t offset)
+{
+ (void)prot;
+ (void)flags;
+ (void)fd;
+ (void)offset;
+
+ int block, ret;
+
+ block = sceKernelAllocMemBlockForVM("code", len);
+ if(block<=0){
+ sceClibPrintf("could not alloc mem block @0x%08X 0x%08X \n", block, len);
+ exit(1);
+ }
+
+ // get base address
+ ret = sceKernelGetMemBlockBase(block, &addr);
+ if (ret < 0)
+ {
+ sceClibPrintf("could get address @0x%08X 0x%08X \n", block, addr);
+ exit(1);
+ }
+
+
+ if(!addr)
+ return MAP_FAILED;
+
+ return addr;
+}
+
+static inline int mprotect(void *addr, size_t len, int prot)
+{
+ (void)addr;
+ (void)len;
+ (void)prot;
+ return 0;
+}
+
+static inline int munmap(void *addr, size_t len)
+{
+ int uid = sceKernelFindMemBlockByAddr(addr, len);
+
+ return sceKernelFreeMemBlock(uid);
+
+}
+
+#ifdef __cplusplus
+};
+#endif
+
+#endif // MMAN_H
diff --git a/frontend/warm b/frontend/warm
deleted file mode 160000
-Subproject a6f015da3b10b82a476250793645c071340decb