mirror of
https://github.com/PCSX2/pcsx2.git
synced 2026-01-31 01:15:24 +01:00
Compare commits
21 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9a75509614 | ||
|
|
c513a29bcf | ||
|
|
5d39c884b5 | ||
|
|
6a0f811812 | ||
|
|
f509fb6950 | ||
|
|
33a475a456 | ||
|
|
d2fb90a700 | ||
|
|
a34467dccd | ||
|
|
c6d0f5e3cd | ||
|
|
34c9590cf1 | ||
|
|
a2c7542e48 | ||
|
|
72a9f18456 | ||
|
|
7f59757eea | ||
|
|
3b89020082 | ||
|
|
a7b07eb53f | ||
|
|
58d13dac34 | ||
|
|
5a8921dd22 | ||
|
|
f964dfaa5e | ||
|
|
17274eb397 | ||
|
|
2f0b00a7a1 | ||
|
|
260380abec |
@@ -22,7 +22,7 @@ jobs:
|
||||
uses: peter-evans/create-pull-request@v7
|
||||
with:
|
||||
title: "PAD: Update to latest controller database"
|
||||
commit-message: "PAD: Update to latest controller database."
|
||||
commit-message: "[ci skip] PAD: Update to latest controller database."
|
||||
committer: "PCSX2 Bot <PCSX2Bot@users.noreply.github.com>"
|
||||
author: "PCSX2 Bot <PCSX2Bot@users.noreply.github.com>"
|
||||
body: "Weekly automatic update of SDL Controller DB."
|
||||
|
||||
@@ -206,7 +206,7 @@ GIT_VERSION=$(git tag --points-at HEAD)
|
||||
|
||||
if [[ "${GIT_VERSION}" == "" ]]; then
|
||||
# In the odd event that we run this script before the release gets tagged.
|
||||
GIT_VERSION=$(git describe --tags)
|
||||
GIT_VERSION=$(git describe --tags || true)
|
||||
if [[ "${GIT_VERSION}" == "" ]]; then
|
||||
GIT_VERSION=$(git rev-parse HEAD)
|
||||
fi
|
||||
|
||||
26
3rdparty/libchdr/include/libchdr/cdrom.h
vendored
26
3rdparty/libchdr/include/libchdr/cdrom.h
vendored
@@ -10,12 +10,10 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
#ifndef __CDROM_H__
|
||||
#define __CDROM_H__
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <libchdr/chdconfig.h>
|
||||
|
||||
/***************************************************************************
|
||||
@@ -49,15 +47,11 @@ enum
|
||||
|
||||
enum
|
||||
{
|
||||
CD_SUB_NONE = 0, /* no subcode data stored */
|
||||
CD_SUB_RAW_INTERLEAVED, /* raw interleaved 96 bytes per sector */
|
||||
CD_SUB_RAW, /* raw non-interleaved 96 bytes per sector */
|
||||
CD_SUB_NORMAL = 0, /* "cooked" 96 bytes per sector */
|
||||
CD_SUB_RAW, /* raw uninterleaved 96 bytes per sector */
|
||||
CD_SUB_NONE /* no subcode data stored */
|
||||
};
|
||||
|
||||
const char* cdrom_get_subtype_string(uint32_t subtype);
|
||||
bool cdrom_parse_subtype_string(const char* typestring, uint32_t* subtype, uint32_t* subsize);
|
||||
|
||||
|
||||
#define CD_FLAG_GDROM 0x00000001 /* disc is a GD-ROM, all tracks should be stored with GD-ROM metadata */
|
||||
#define CD_FLAG_GDROMLE 0x00000002 /* legacy GD-ROM, with little-endian CDDA data */
|
||||
|
||||
@@ -87,10 +81,10 @@ static inline uint32_t lba_to_msf(uint32_t lba)
|
||||
{
|
||||
uint8_t m, s, f;
|
||||
|
||||
m = (uint8_t)(lba / (60 * 75));
|
||||
m = lba / (60 * 75);
|
||||
lba -= m * (60 * 75);
|
||||
s = (uint8_t)(lba / 75);
|
||||
f = (uint8_t)(lba % 75);
|
||||
s = lba / 75;
|
||||
f = lba % 75;
|
||||
|
||||
return ((m / 10) << 20) | ((m % 10) << 16) |
|
||||
((s / 10) << 12) | ((s % 10) << 8) |
|
||||
@@ -113,6 +107,4 @@ static inline uint32_t lba_to_msf_alt(int lba)
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
#endif /* __CDROM_H__ */
|
||||
|
||||
204
3rdparty/libchdr/include/libchdr/chd.h
vendored
204
3rdparty/libchdr/include/libchdr/chd.h
vendored
@@ -48,7 +48,6 @@ extern "C" {
|
||||
|
||||
#include <libchdr/coretypes.h>
|
||||
#include <libchdr/chdconfig.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
/***************************************************************************
|
||||
|
||||
@@ -59,67 +58,67 @@ extern "C" {
|
||||
V1 header:
|
||||
|
||||
[ 0] char tag[8]; // 'MComprHD'
|
||||
[ 8] UINT32 length; // length of header (including tag and length fields)
|
||||
[ 12] UINT32 version; // drive format version
|
||||
[ 16] UINT32 flags; // flags (see below)
|
||||
[ 20] UINT32 compression; // compression type
|
||||
[ 24] UINT32 hunksize; // 512-byte sectors per hunk
|
||||
[ 28] UINT32 totalhunks; // total # of hunks represented
|
||||
[ 32] UINT32 cylinders; // number of cylinders on hard disk
|
||||
[ 36] UINT32 heads; // number of heads on hard disk
|
||||
[ 40] UINT32 sectors; // number of sectors on hard disk
|
||||
[ 44] UINT8 md5[16]; // MD5 checksum of raw data
|
||||
[ 60] UINT8 parentmd5[16]; // MD5 checksum of parent file
|
||||
[ 8] uint32_t length; // length of header (including tag and length fields)
|
||||
[ 12] uint32_t version; // drive format version
|
||||
[ 16] uint32_t flags; // flags (see below)
|
||||
[ 20] uint32_t compression; // compression type
|
||||
[ 24] uint32_t hunksize; // 512-byte sectors per hunk
|
||||
[ 28] uint32_t totalhunks; // total # of hunks represented
|
||||
[ 32] uint32_t cylinders; // number of cylinders on hard disk
|
||||
[ 36] uint32_t heads; // number of heads on hard disk
|
||||
[ 40] uint32_t sectors; // number of sectors on hard disk
|
||||
[ 44] uint8_t md5[16]; // MD5 checksum of raw data
|
||||
[ 60] uint8_t parentmd5[16]; // MD5 checksum of parent file
|
||||
[ 76] (V1 header length)
|
||||
|
||||
V2 header:
|
||||
|
||||
[ 0] char tag[8]; // 'MComprHD'
|
||||
[ 8] UINT32 length; // length of header (including tag and length fields)
|
||||
[ 12] UINT32 version; // drive format version
|
||||
[ 16] UINT32 flags; // flags (see below)
|
||||
[ 20] UINT32 compression; // compression type
|
||||
[ 24] UINT32 hunksize; // seclen-byte sectors per hunk
|
||||
[ 28] UINT32 totalhunks; // total # of hunks represented
|
||||
[ 32] UINT32 cylinders; // number of cylinders on hard disk
|
||||
[ 36] UINT32 heads; // number of heads on hard disk
|
||||
[ 40] UINT32 sectors; // number of sectors on hard disk
|
||||
[ 44] UINT8 md5[16]; // MD5 checksum of raw data
|
||||
[ 60] UINT8 parentmd5[16]; // MD5 checksum of parent file
|
||||
[ 76] UINT32 seclen; // number of bytes per sector
|
||||
[ 8] uint32_t length; // length of header (including tag and length fields)
|
||||
[ 12] uint32_t version; // drive format version
|
||||
[ 16] uint32_t flags; // flags (see below)
|
||||
[ 20] uint32_t compression; // compression type
|
||||
[ 24] uint32_t hunksize; // seclen-byte sectors per hunk
|
||||
[ 28] uint32_t totalhunks; // total # of hunks represented
|
||||
[ 32] uint32_t cylinders; // number of cylinders on hard disk
|
||||
[ 36] uint32_t heads; // number of heads on hard disk
|
||||
[ 40] uint32_t sectors; // number of sectors on hard disk
|
||||
[ 44] uint8_t md5[16]; // MD5 checksum of raw data
|
||||
[ 60] uint8_t parentmd5[16]; // MD5 checksum of parent file
|
||||
[ 76] uint32_t seclen; // number of bytes per sector
|
||||
[ 80] (V2 header length)
|
||||
|
||||
V3 header:
|
||||
|
||||
[ 0] char tag[8]; // 'MComprHD'
|
||||
[ 8] UINT32 length; // length of header (including tag and length fields)
|
||||
[ 12] UINT32 version; // drive format version
|
||||
[ 16] UINT32 flags; // flags (see below)
|
||||
[ 20] UINT32 compression; // compression type
|
||||
[ 24] UINT32 totalhunks; // total # of hunks represented
|
||||
[ 28] UINT64 logicalbytes; // logical size of the data (in bytes)
|
||||
[ 36] UINT64 metaoffset; // offset to the first blob of metadata
|
||||
[ 44] UINT8 md5[16]; // MD5 checksum of raw data
|
||||
[ 60] UINT8 parentmd5[16]; // MD5 checksum of parent file
|
||||
[ 76] UINT32 hunkbytes; // number of bytes per hunk
|
||||
[ 80] UINT8 sha1[20]; // SHA1 checksum of raw data
|
||||
[100] UINT8 parentsha1[20];// SHA1 checksum of parent file
|
||||
[ 8] uint32_t length; // length of header (including tag and length fields)
|
||||
[ 12] uint32_t version; // drive format version
|
||||
[ 16] uint32_t flags; // flags (see below)
|
||||
[ 20] uint32_t compression; // compression type
|
||||
[ 24] uint32_t totalhunks; // total # of hunks represented
|
||||
[ 28] uint64_t logicalbytes; // logical size of the data (in bytes)
|
||||
[ 36] uint64_t metaoffset; // offset to the first blob of metadata
|
||||
[ 44] uint8_t md5[16]; // MD5 checksum of raw data
|
||||
[ 60] uint8_t parentmd5[16]; // MD5 checksum of parent file
|
||||
[ 76] uint32_t hunkbytes; // number of bytes per hunk
|
||||
[ 80] uint8_t sha1[20]; // SHA1 checksum of raw data
|
||||
[100] uint8_t parentsha1[20];// SHA1 checksum of parent file
|
||||
[120] (V3 header length)
|
||||
|
||||
V4 header:
|
||||
|
||||
[ 0] char tag[8]; // 'MComprHD'
|
||||
[ 8] UINT32 length; // length of header (including tag and length fields)
|
||||
[ 12] UINT32 version; // drive format version
|
||||
[ 16] UINT32 flags; // flags (see below)
|
||||
[ 20] UINT32 compression; // compression type
|
||||
[ 24] UINT32 totalhunks; // total # of hunks represented
|
||||
[ 28] UINT64 logicalbytes; // logical size of the data (in bytes)
|
||||
[ 36] UINT64 metaoffset; // offset to the first blob of metadata
|
||||
[ 44] UINT32 hunkbytes; // number of bytes per hunk
|
||||
[ 48] UINT8 sha1[20]; // combined raw+meta SHA1
|
||||
[ 68] UINT8 parentsha1[20];// combined raw+meta SHA1 of parent
|
||||
[ 88] UINT8 rawsha1[20]; // raw data SHA1
|
||||
[ 8] uint32_t length; // length of header (including tag and length fields)
|
||||
[ 12] uint32_t version; // drive format version
|
||||
[ 16] uint32_t flags; // flags (see below)
|
||||
[ 20] uint32_t compression; // compression type
|
||||
[ 24] uint32_t totalhunks; // total # of hunks represented
|
||||
[ 28] uint64_t logicalbytes; // logical size of the data (in bytes)
|
||||
[ 36] uint64_t metaoffset; // offset to the first blob of metadata
|
||||
[ 44] uint32_t hunkbytes; // number of bytes per hunk
|
||||
[ 48] uint8_t sha1[20]; // combined raw+meta SHA1
|
||||
[ 68] uint8_t parentsha1[20];// combined raw+meta SHA1 of parent
|
||||
[ 88] uint8_t rawsha1[20]; // raw data SHA1
|
||||
[108] (V4 header length)
|
||||
|
||||
Flags:
|
||||
@@ -131,17 +130,17 @@ extern "C" {
|
||||
V5 header:
|
||||
|
||||
[ 0] char tag[8]; // 'MComprHD'
|
||||
[ 8] uint32_t length; // length of header (including tag and length fields)
|
||||
[ 12] uint32_t version; // drive format version
|
||||
[ 16] uint32_t compressors[4];// which custom compressors are used?
|
||||
[ 32] uint64_t logicalbytes; // logical size of the data (in bytes)
|
||||
[ 40] uint64_t mapoffset; // offset to the map
|
||||
[ 48] uint64_t metaoffset; // offset to the first blob of metadata
|
||||
[ 56] uint32_t hunkbytes; // number of bytes per hunk (512k maximum)
|
||||
[ 60] uint32_t unitbytes; // number of bytes per unit within each hunk
|
||||
[ 64] uint8_t rawsha1[20]; // raw data SHA1
|
||||
[ 84] uint8_t sha1[20]; // combined raw+meta SHA1
|
||||
[104] uint8_t parentsha1[20];// combined raw+meta SHA1 of parent
|
||||
[ 8] uint32_t_t length; // length of header (including tag and length fields)
|
||||
[ 12] uint32_t_t version; // drive format version
|
||||
[ 16] uint32_t_t compressors[4];// which custom compressors are used?
|
||||
[ 32] uint64_t_t logicalbytes; // logical size of the data (in bytes)
|
||||
[ 40] uint64_t_t mapoffset; // offset to the map
|
||||
[ 48] uint64_t_t metaoffset; // offset to the first blob of metadata
|
||||
[ 56] uint32_t_t hunkbytes; // number of bytes per hunk (512k maximum)
|
||||
[ 60] uint32_t_t unitbytes; // number of bytes per unit within each hunk
|
||||
[ 64] uint8_t_t rawsha1[20]; // raw data SHA1
|
||||
[ 84] uint8_t_t sha1[20]; // combined raw+meta SHA1
|
||||
[104] uint8_t_t parentsha1[20];// combined raw+meta SHA1 of parent
|
||||
[124] (V5 header length)
|
||||
|
||||
If parentsha1 != 0, we have a parent (no need for flags)
|
||||
@@ -149,22 +148,22 @@ extern "C" {
|
||||
|
||||
V5 uncompressed map format:
|
||||
|
||||
[ 0] uint32_t offset; // starting offset / hunk size
|
||||
[ 0] uint32_t_t offset; // starting offset / hunk size
|
||||
|
||||
V5 compressed map format header:
|
||||
|
||||
[ 0] uint32_t length; // length of compressed map
|
||||
[ 0] uint32_t_t length; // length of compressed map
|
||||
[ 4] UINT48 datastart; // offset of first block
|
||||
[ 10] uint16_t crc; // crc-16 of the map
|
||||
[ 12] uint8_t lengthbits; // bits used to encode complength
|
||||
[ 13] uint8_t hunkbits; // bits used to encode self-refs
|
||||
[ 14] uint8_t parentunitbits; // bits used to encode parent unit refs
|
||||
[ 15] uint8_t reserved; // future use
|
||||
[ 12] uint8_t_t lengthbits; // bits used to encode complength
|
||||
[ 13] uint8_t_t hunkbits; // bits used to encode self-refs
|
||||
[ 14] uint8_t_t parentunitbits; // bits used to encode parent unit refs
|
||||
[ 15] uint8_t_t reserved; // future use
|
||||
[ 16] (compressed header length)
|
||||
|
||||
Each compressed map entry, once expanded, looks like:
|
||||
|
||||
[ 0] uint8_t compression; // compression type
|
||||
[ 0] uint8_t_t compression; // compression type
|
||||
[ 1] UINT24 complength; // compressed length
|
||||
[ 4] UINT48 offset; // offset
|
||||
[ 10] uint16_t crc; // crc-16 of the data
|
||||
@@ -221,7 +220,7 @@ extern "C" {
|
||||
|
||||
/* metadata parameters */
|
||||
#define CHDMETATAG_WILDCARD 0
|
||||
#define CHD_METAINDEX_APPEND ((UINT32)-1)
|
||||
#define CHD_METAINDEX_APPEND ((uint32_t)-1)
|
||||
|
||||
/* metadata flags */
|
||||
#define CHD_MDFLAGS_CHECKSUM 0x01 /* indicates data is checksummed */
|
||||
@@ -290,8 +289,7 @@ enum _chd_error
|
||||
CHDERR_INVALID_STATE,
|
||||
CHDERR_OPERATION_PENDING,
|
||||
CHDERR_NO_ASYNC_OPERATION,
|
||||
CHDERR_UNSUPPORTED_FORMAT,
|
||||
CHDERR_CANCELLED,
|
||||
CHDERR_UNSUPPORTED_FORMAT
|
||||
};
|
||||
typedef enum _chd_error chd_error;
|
||||
|
||||
@@ -309,32 +307,32 @@ typedef struct _chd_file chd_file;
|
||||
typedef struct _chd_header chd_header;
|
||||
struct _chd_header
|
||||
{
|
||||
UINT32 length; /* length of header data */
|
||||
UINT32 version; /* drive format version */
|
||||
UINT32 flags; /* flags field */
|
||||
UINT32 compression[4]; /* compression type */
|
||||
UINT32 hunkbytes; /* number of bytes per hunk */
|
||||
UINT32 totalhunks; /* total # of hunks represented */
|
||||
UINT64 logicalbytes; /* logical size of the data */
|
||||
UINT64 metaoffset; /* offset in file of first metadata */
|
||||
UINT64 mapoffset; /* TOOD V5 */
|
||||
UINT8 md5[CHD_MD5_BYTES]; /* overall MD5 checksum */
|
||||
UINT8 parentmd5[CHD_MD5_BYTES]; /* overall MD5 checksum of parent */
|
||||
UINT8 sha1[CHD_SHA1_BYTES]; /* overall SHA1 checksum */
|
||||
UINT8 rawsha1[CHD_SHA1_BYTES]; /* SHA1 checksum of raw data */
|
||||
UINT8 parentsha1[CHD_SHA1_BYTES]; /* overall SHA1 checksum of parent */
|
||||
UINT32 unitbytes; /* TODO V5 */
|
||||
UINT64 unitcount; /* TODO V5 */
|
||||
UINT32 hunkcount; /* TODO V5 */
|
||||
uint32_t length; /* length of header data */
|
||||
uint32_t version; /* drive format version */
|
||||
uint32_t flags; /* flags field */
|
||||
uint32_t compression[4]; /* compression type */
|
||||
uint32_t hunkbytes; /* number of bytes per hunk */
|
||||
uint32_t totalhunks; /* total # of hunks represented */
|
||||
uint64_t logicalbytes; /* logical size of the data */
|
||||
uint64_t metaoffset; /* offset in file of first metadata */
|
||||
uint64_t mapoffset; /* TOOD V5 */
|
||||
uint8_t md5[CHD_MD5_BYTES]; /* overall MD5 checksum */
|
||||
uint8_t parentmd5[CHD_MD5_BYTES]; /* overall MD5 checksum of parent */
|
||||
uint8_t sha1[CHD_SHA1_BYTES]; /* overall SHA1 checksum */
|
||||
uint8_t rawsha1[CHD_SHA1_BYTES]; /* SHA1 checksum of raw data */
|
||||
uint8_t parentsha1[CHD_SHA1_BYTES]; /* overall SHA1 checksum of parent */
|
||||
uint32_t unitbytes; /* TODO V5 */
|
||||
uint64_t unitcount; /* TODO V5 */
|
||||
uint32_t hunkcount; /* TODO V5 */
|
||||
|
||||
/* map information */
|
||||
UINT32 mapentrybytes; /* length of each entry in a map (V5) */
|
||||
UINT8* rawmap; /* raw map data */
|
||||
uint32_t mapentrybytes; /* length of each entry in a map (V5) */
|
||||
uint8_t* rawmap; /* raw map data */
|
||||
|
||||
UINT32 obsolete_cylinders; /* obsolete field -- do not use! */
|
||||
UINT32 obsolete_sectors; /* obsolete field -- do not use! */
|
||||
UINT32 obsolete_heads; /* obsolete field -- do not use! */
|
||||
UINT32 obsolete_hunksize; /* obsolete field -- do not use! */
|
||||
uint32_t obsolete_cylinders; /* obsolete field -- do not use! */
|
||||
uint32_t obsolete_sectors; /* obsolete field -- do not use! */
|
||||
uint32_t obsolete_heads; /* obsolete field -- do not use! */
|
||||
uint32_t obsolete_hunksize; /* obsolete field -- do not use! */
|
||||
};
|
||||
|
||||
|
||||
@@ -342,10 +340,10 @@ struct _chd_header
|
||||
typedef struct _chd_verify_result chd_verify_result;
|
||||
struct _chd_verify_result
|
||||
{
|
||||
UINT8 md5[CHD_MD5_BYTES]; /* overall MD5 checksum */
|
||||
UINT8 sha1[CHD_SHA1_BYTES]; /* overall SHA1 checksum */
|
||||
UINT8 rawsha1[CHD_SHA1_BYTES]; /* SHA1 checksum of raw data */
|
||||
UINT8 metasha1[CHD_SHA1_BYTES]; /* SHA1 checksum of metadata */
|
||||
uint8_t md5[CHD_MD5_BYTES]; /* overall MD5 checksum */
|
||||
uint8_t sha1[CHD_SHA1_BYTES]; /* overall SHA1 checksum */
|
||||
uint8_t rawsha1[CHD_SHA1_BYTES]; /* SHA1 checksum of raw data */
|
||||
uint8_t metasha1[CHD_SHA1_BYTES]; /* SHA1 checksum of metadata */
|
||||
};
|
||||
|
||||
|
||||
@@ -371,10 +369,10 @@ struct _chd_verify_result
|
||||
/* ----- CHD file management ----- */
|
||||
|
||||
/* create a new CHD file fitting the given description */
|
||||
/* chd_error chd_create(const char *filename, UINT64 logicalbytes, UINT32 hunkbytes, UINT32 compression, chd_file *parent); */
|
||||
/* chd_error chd_create(const char *filename, uint64_t logicalbytes, uint32_t hunkbytes, uint32_t compression, chd_file *parent); */
|
||||
|
||||
/* same as chd_create(), but accepts an already-opened core_file object */
|
||||
/* chd_error chd_create_file(core_file *file, UINT64 logicalbytes, UINT32 hunkbytes, UINT32 compression, chd_file *parent); */
|
||||
/* chd_error chd_create_file(core_file *file, uint64_t logicalbytes, uint32_t hunkbytes, uint32_t compression, chd_file *parent); */
|
||||
|
||||
/* open an existing CHD file */
|
||||
CHD_EXPORT chd_error chd_open_core_file(core_file *file, int mode, chd_file *parent, chd_file **chd);
|
||||
@@ -383,7 +381,6 @@ CHD_EXPORT chd_error chd_open(const char *filename, int mode, chd_file *parent,
|
||||
|
||||
/* precache underlying file */
|
||||
CHD_EXPORT chd_error chd_precache(chd_file *chd);
|
||||
CHD_EXPORT chd_error chd_precache_progress(chd_file* chd, bool(*progress)(size_t pos, size_t total, void* param), void* param);
|
||||
|
||||
/* close a CHD file */
|
||||
CHD_EXPORT void chd_close(chd_file *chd);
|
||||
@@ -391,13 +388,11 @@ CHD_EXPORT void chd_close(chd_file *chd);
|
||||
/* return the associated core_file */
|
||||
CHD_EXPORT core_file *chd_core_file(chd_file *chd);
|
||||
|
||||
/* return the overall size of a CHD, and any of its parents */
|
||||
CHD_EXPORT UINT64 chd_get_compressed_size(chd_file* chd);
|
||||
|
||||
/* return an error string for the given CHD error */
|
||||
CHD_EXPORT const char *chd_error_string(chd_error err);
|
||||
|
||||
|
||||
|
||||
/* ----- CHD header management ----- */
|
||||
|
||||
/* return a pointer to the extracted CHD header data */
|
||||
@@ -407,21 +402,20 @@ CHD_EXPORT const chd_header *chd_get_header(chd_file *chd);
|
||||
CHD_EXPORT chd_error chd_read_header_core_file(core_file *file, chd_header *header);
|
||||
CHD_EXPORT chd_error chd_read_header_file(FILE *file, chd_header *header);
|
||||
CHD_EXPORT chd_error chd_read_header(const char *filename, chd_header *header);
|
||||
CHD_EXPORT bool chd_is_matching_parent(const chd_header* header, const chd_header* parent_header);
|
||||
|
||||
|
||||
|
||||
/* ----- core data read/write ----- */
|
||||
|
||||
/* read one hunk from the CHD file */
|
||||
CHD_EXPORT chd_error chd_read(chd_file *chd, UINT32 hunknum, void *buffer);
|
||||
CHD_EXPORT chd_error chd_read(chd_file *chd, uint32_t hunknum, void *buffer);
|
||||
|
||||
|
||||
|
||||
/* ----- metadata management ----- */
|
||||
|
||||
/* get indexed metadata of a particular sort */
|
||||
CHD_EXPORT chd_error chd_get_metadata(chd_file *chd, UINT32 searchtag, UINT32 searchindex, void *output, UINT32 outputlen, UINT32 *resultlen, UINT32 *resulttag, UINT8 *resultflags);
|
||||
CHD_EXPORT chd_error chd_get_metadata(chd_file *chd, uint32_t searchtag, uint32_t searchindex, void *output, uint32_t outputlen, uint32_t *resultlen, uint32_t *resulttag, uint8_t *resultflags);
|
||||
|
||||
|
||||
|
||||
@@ -432,7 +426,7 @@ CHD_EXPORT chd_error chd_get_metadata(chd_file *chd, UINT32 searchtag, UINT32 se
|
||||
CHD_EXPORT chd_error chd_codec_config(chd_file *chd, int param, void *config);
|
||||
|
||||
/* return a string description of a codec */
|
||||
CHD_EXPORT const char *chd_get_codec_name(UINT32 codec);
|
||||
CHD_EXPORT const char *chd_get_codec_name(uint32_t codec);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
31
3rdparty/libchdr/include/libchdr/coretypes.h
vendored
31
3rdparty/libchdr/include/libchdr/coretypes.h
vendored
@@ -8,26 +8,13 @@
|
||||
#include <streams/file_stream_transforms.h>
|
||||
#endif
|
||||
|
||||
#ifndef ARRAY_LENGTH
|
||||
#define ARRAY_LENGTH(x) (sizeof(x)/sizeof(x[0]))
|
||||
|
||||
#if defined(__PS3__) || defined(__PSL1GHT__)
|
||||
#undef UINT32
|
||||
#undef UINT16
|
||||
#undef UINT8
|
||||
#undef INT32
|
||||
#undef INT16
|
||||
#undef INT8
|
||||
#endif
|
||||
|
||||
typedef uint64_t UINT64;
|
||||
typedef uint32_t UINT32;
|
||||
typedef uint16_t UINT16;
|
||||
typedef uint8_t UINT8;
|
||||
|
||||
typedef int64_t INT64;
|
||||
typedef int32_t INT32;
|
||||
typedef int16_t INT16;
|
||||
typedef int8_t INT8;
|
||||
#ifndef ARRAY_SIZE
|
||||
#define ARRAY_SIZE(x) (sizeof(x)/sizeof(x[0]))
|
||||
#endif
|
||||
|
||||
typedef struct chd_core_file {
|
||||
/*
|
||||
@@ -41,9 +28,9 @@ typedef struct chd_core_file {
|
||||
* undefined because many implementations will seek to the end of the
|
||||
* file and call ftell.
|
||||
*
|
||||
* on error, (UINT64)-1 is returned.
|
||||
* on error, (uint64_t)-1 is returned.
|
||||
*/
|
||||
UINT64(*fsize)(struct chd_core_file*);
|
||||
uint64_t(*fsize)(struct chd_core_file*);
|
||||
|
||||
/*
|
||||
* should match the behavior of fread, except the FILE* argument at the end
|
||||
@@ -55,7 +42,7 @@ typedef struct chd_core_file {
|
||||
int (*fclose)(struct chd_core_file*);
|
||||
|
||||
// fseek clone
|
||||
int (*fseek)(struct chd_core_file*, INT64, int);
|
||||
int (*fseek)(struct chd_core_file*, int64_t, int);
|
||||
} core_file;
|
||||
|
||||
static inline int core_fclose(core_file *fp) {
|
||||
@@ -66,11 +53,11 @@ static inline size_t core_fread(core_file *fp, void *ptr, size_t len) {
|
||||
return fp->fread(ptr, 1, len, fp);
|
||||
}
|
||||
|
||||
static inline int core_fseek(core_file* fp, INT64 offset, int whence) {
|
||||
static inline int core_fseek(core_file* fp, int64_t offset, int whence) {
|
||||
return fp->fseek(fp, offset, whence);
|
||||
}
|
||||
|
||||
static inline UINT64 core_fsize(core_file *fp)
|
||||
static inline uint64_t core_fsize(core_file *fp)
|
||||
{
|
||||
return fp->fsize(fp);
|
||||
}
|
||||
|
||||
2
3rdparty/libchdr/include/libchdr/huffman.h
vendored
2
3rdparty/libchdr/include/libchdr/huffman.h
vendored
@@ -85,6 +85,6 @@ int huffman_build_tree(struct huffman_decoder* decoder, uint32_t totaldata, uint
|
||||
enum huffman_error huffman_assign_canonical_codes(struct huffman_decoder* decoder);
|
||||
enum huffman_error huffman_compute_tree_from_histo(struct huffman_decoder* decoder);
|
||||
|
||||
void huffman_build_lookup_table(struct huffman_decoder* decoder);
|
||||
enum huffman_error huffman_build_lookup_table(struct huffman_decoder* decoder);
|
||||
|
||||
#endif
|
||||
|
||||
29
3rdparty/libchdr/src/libchdr_cdrom.c
vendored
29
3rdparty/libchdr/src/libchdr_cdrom.c
vendored
@@ -20,35 +20,6 @@
|
||||
|
||||
#include <libchdr/cdrom.h>
|
||||
|
||||
const char* cdrom_get_subtype_string(uint32_t subtype)
|
||||
{
|
||||
switch (subtype)
|
||||
{
|
||||
case CD_SUB_RAW: return "RW";
|
||||
case CD_SUB_RAW_INTERLEAVED: return "RW_RAW";
|
||||
default: return "NONE";
|
||||
}
|
||||
}
|
||||
|
||||
bool cdrom_parse_subtype_string(const char* typestring, uint32_t* subtype, uint32_t* subsize)
|
||||
{
|
||||
// https://github.com/mamedev/mame/blob/d2d54fb8ed53a2e86d308067da8414f85b5929b0/src/lib/util/cdrom.cpp#L767
|
||||
if (!strcmp(typestring, "RW"))
|
||||
{
|
||||
*subtype = CD_SUB_RAW;
|
||||
*subsize = 96;
|
||||
return true;
|
||||
}
|
||||
else if (!strcmp(typestring, "RW_RAW"))
|
||||
{
|
||||
*subtype = CD_SUB_RAW_INTERLEAVED;
|
||||
*subsize = 96;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifdef WANT_RAW_DATA_SECTOR
|
||||
|
||||
/***************************************************************************
|
||||
|
||||
622
3rdparty/libchdr/src/libchdr_chd.c
vendored
622
3rdparty/libchdr/src/libchdr_chd.c
vendored
File diff suppressed because it is too large
Load Diff
32
3rdparty/libchdr/src/libchdr_huffman.c
vendored
32
3rdparty/libchdr/src/libchdr_huffman.c
vendored
@@ -230,7 +230,9 @@ enum huffman_error huffman_import_tree_rle(struct huffman_decoder* decoder, stru
|
||||
return error;
|
||||
|
||||
/* build the lookup table */
|
||||
huffman_build_lookup_table(decoder);
|
||||
error = huffman_build_lookup_table(decoder);
|
||||
if (error != HUFFERR_NONE)
|
||||
return error;
|
||||
|
||||
/* determine final input length and report errors */
|
||||
return bitstream_overflow(bitbuf) ? HUFFERR_INPUT_BUFFER_TOO_SMALL : HUFFERR_NONE;
|
||||
@@ -271,8 +273,16 @@ enum huffman_error huffman_import_tree_huffman(struct huffman_decoder* decoder,
|
||||
/* then regenerate the tree */
|
||||
error = huffman_assign_canonical_codes(smallhuff);
|
||||
if (error != HUFFERR_NONE)
|
||||
{
|
||||
delete_huffman_decoder(smallhuff);
|
||||
return error;
|
||||
huffman_build_lookup_table(smallhuff);
|
||||
}
|
||||
error = huffman_build_lookup_table(smallhuff);
|
||||
if (error != HUFFERR_NONE)
|
||||
{
|
||||
delete_huffman_decoder(smallhuff);
|
||||
return error;
|
||||
}
|
||||
|
||||
/* determine the maximum length of an RLE count */
|
||||
temp = decoder->numcodes - 9;
|
||||
@@ -308,7 +318,9 @@ enum huffman_error huffman_import_tree_huffman(struct huffman_decoder* decoder,
|
||||
return error;
|
||||
|
||||
/* build the lookup table */
|
||||
huffman_build_lookup_table(decoder);
|
||||
error = huffman_build_lookup_table(decoder);
|
||||
if (error != HUFFERR_NONE)
|
||||
return error;
|
||||
|
||||
/* determine final input length and report errors */
|
||||
return bitstream_overflow(bitbuf) ? HUFFERR_INPUT_BUFFER_TOO_SMALL : HUFFERR_NONE;
|
||||
@@ -523,8 +535,9 @@ enum huffman_error huffman_assign_canonical_codes(struct huffman_decoder* decode
|
||||
*-------------------------------------------------
|
||||
*/
|
||||
|
||||
void huffman_build_lookup_table(struct huffman_decoder* decoder)
|
||||
enum huffman_error huffman_build_lookup_table(struct huffman_decoder* decoder)
|
||||
{
|
||||
const lookup_value* lookupend = &decoder->lookup[(1u << decoder->maxbits)];
|
||||
uint32_t curcode;
|
||||
/* iterate over all codes */
|
||||
for (curcode = 0; curcode < decoder->numcodes; curcode++)
|
||||
@@ -533,9 +546,10 @@ void huffman_build_lookup_table(struct huffman_decoder* decoder)
|
||||
struct node_t* node = &decoder->huffnode[curcode];
|
||||
if (node->numbits > 0)
|
||||
{
|
||||
int shift;
|
||||
lookup_value *dest;
|
||||
lookup_value *destend;
|
||||
int shift;
|
||||
lookup_value *dest;
|
||||
lookup_value *destend;
|
||||
|
||||
/* set up the entry */
|
||||
lookup_value value = MAKE_LOOKUP(curcode, node->numbits);
|
||||
|
||||
@@ -543,8 +557,12 @@ void huffman_build_lookup_table(struct huffman_decoder* decoder)
|
||||
shift = decoder->maxbits - node->numbits;
|
||||
dest = &decoder->lookup[node->bits << shift];
|
||||
destend = &decoder->lookup[((node->bits + 1) << shift) - 1];
|
||||
if (dest >= lookupend || destend >= lookupend || destend < dest)
|
||||
return HUFFERR_INTERNAL_INCONSISTENCY;
|
||||
while (dest <= destend)
|
||||
*dest++ = value;
|
||||
}
|
||||
}
|
||||
|
||||
return HUFFERR_NONE;
|
||||
}
|
||||
|
||||
@@ -5367,6 +5367,7 @@ SCES-52033:
|
||||
autoFlush: 2 # Fixes lights going through walls.
|
||||
preloadFrameData: 1 # Fixes light flicker.
|
||||
halfPixelOffset: 2 # Corrects light position.
|
||||
bilinearUpscale: 1 # Smooths out bloom on lights.
|
||||
gameFixes:
|
||||
- EETimingHack # Fixes random hangs.
|
||||
patches:
|
||||
@@ -7075,6 +7076,7 @@ SCKA-20032:
|
||||
autoFlush: 2 # Fixes lights going through walls.
|
||||
preloadFrameData: 1 # Fixes light flicker.
|
||||
halfPixelOffset: 2 # Corrects light position.
|
||||
bilinearUpscale: 1 # Smooths out bloom on lights.
|
||||
gameFixes:
|
||||
- EETimingHack # Fixes random hangs.
|
||||
patches:
|
||||
@@ -11107,6 +11109,7 @@ SCUS-97264:
|
||||
autoFlush: 2 # Fixes lights going through walls.
|
||||
preloadFrameData: 1 # Fixes light flicker.
|
||||
halfPixelOffset: 2 # Corrects light position.
|
||||
bilinearUpscale: 1 # Smooths out bloom on lights.
|
||||
gameFixes:
|
||||
- EETimingHack # Fixes random hangs.
|
||||
patches:
|
||||
@@ -11449,6 +11452,7 @@ SCUS-97377:
|
||||
autoFlush: 2 # Fixes lights going through walls.
|
||||
preloadFrameData: 1 # Fixes light flicker.
|
||||
halfPixelOffset: 2 # Corrects light position.
|
||||
bilinearUpscale: 1 # Smooths out bloom on lights.
|
||||
SCUS-97378:
|
||||
name: "EyeToy and EyeToy Play [Demo]"
|
||||
region: "NTSC-U"
|
||||
@@ -12153,6 +12157,7 @@ SCUS-97520:
|
||||
autoFlush: 2 # Fixes lights going through walls.
|
||||
preloadFrameData: 1 # Fixes light flicker.
|
||||
halfPixelOffset: 2 # Corrects light position.
|
||||
bilinearUpscale: 1 # Smooths out bloom on lights.
|
||||
SCUS-97523:
|
||||
name: "EyeToy - Operation Spy!"
|
||||
region: "NTSC-U"
|
||||
@@ -12419,7 +12424,7 @@ SCUS-97621:
|
||||
clampModes:
|
||||
vu1ClampMode: 3 # Fixes missing textures.
|
||||
gsHWFixes:
|
||||
recommendedBlendingLevel: 2 # Fixes smoke effects.
|
||||
recommendedBlendingLevel: 4 # Fixes menu text brightness and smoke effects.
|
||||
gameFixes:
|
||||
- VUSyncHack # Fixes black doors on vehicles.
|
||||
patches:
|
||||
@@ -24567,6 +24572,8 @@ SLES-54152:
|
||||
name: "The Ant Bully"
|
||||
name-sort: "Ant Bully, The"
|
||||
region: "PAL-M5"
|
||||
gsHWFixes:
|
||||
nativeScaling: 2 # Fixes misaligned post effects.
|
||||
SLES-54153:
|
||||
name: "Virtua Pro Football"
|
||||
region: "PAL-M5"
|
||||
@@ -24691,6 +24698,8 @@ SLES-54178:
|
||||
name: "The Ant Bully"
|
||||
name-sort: "Ant Bully, The"
|
||||
region: "PAL-E-F"
|
||||
gsHWFixes:
|
||||
nativeScaling: 2 # Fixes misaligned post effects.
|
||||
SLES-54179:
|
||||
name: "Pirates of the Caribbean - At World's End"
|
||||
region: "PAL-M6"
|
||||
@@ -56525,6 +56534,8 @@ SLPS-25426:
|
||||
name-sort: "めいたんていこなん だいえいていこくのいさん"
|
||||
name-en: "Detective Conan - Inheritance of Britain"
|
||||
region: "NTSC-J"
|
||||
gsHWFixes:
|
||||
halfPixelOffset: 2 # Fixes misaligned blur in game and on the UI.
|
||||
SLPS-25427:
|
||||
name: "レジェンズ 激闘!サーガバトル"
|
||||
name-sort: "れじぇんず げきとう さーがばとる"
|
||||
@@ -57432,6 +57443,8 @@ SLPS-25588:
|
||||
name-sort: "めいたんていこなん だいえいていこくのいさん BANDAI THE BEST"
|
||||
name-en: "Meitantei Conan - Daiei Teikoku no Isan [Bandai The Best]"
|
||||
region: "NTSC-J"
|
||||
gsHWFixes:
|
||||
halfPixelOffset: 2 # Fixes misaligned blur in game and on the UI.
|
||||
SLPS-25589:
|
||||
name: "NARUTO-ナルト- ナルティメットヒーロー3"
|
||||
name-sort: "なると なるてぃめっとひーろー3"
|
||||
@@ -68410,6 +68423,8 @@ SLUS-21415:
|
||||
name-sort: "Ant Bully, The"
|
||||
region: "NTSC-U"
|
||||
compat: 5
|
||||
gsHWFixes:
|
||||
nativeScaling: 2 # Fixes misaligned post effects.
|
||||
SLUS-21416:
|
||||
name: "D1 Grand Prix Series - Professional Drift"
|
||||
region: "NTSC-U"
|
||||
@@ -72231,6 +72246,7 @@ TCES-52033:
|
||||
autoFlush: 2 # Fixes lights going through walls.
|
||||
preloadFrameData: 1 # Fixes light flicker.
|
||||
halfPixelOffset: 2 # Corrects light position.
|
||||
bilinearUpscale: 1 # Smooths out bloom on lights.
|
||||
gameFixes:
|
||||
- EETimingHack # Fixes random hangs.
|
||||
patches:
|
||||
|
||||
@@ -593,6 +593,7 @@
|
||||
030000009b2800002c00000000000000,Raphnet Wii Classic Adapter,a:b1,b:b4,back:b2,dpdown:b13,dpleft:b14,dpright:b15,dpup:b12,guide:b10,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a3,righty:a4,start:b3,x:b0,y:b5,platform:Windows,
|
||||
030000009b2800008000000000000000,Raphnet Wii Classic Adapter,a:b1,b:b4,back:b2,dpdown:b13,dpleft:b14,dpright:b15,dpup:b12,guide:b10,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a3,righty:a4,start:b3,x:b0,y:b5,platform:Windows,
|
||||
03000000790000008f18000000000000,Rapoo Gamepad,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b3,y:b0,platform:Windows,
|
||||
0300000032150000a602000000000000,Razer Huntsman V3 Pro,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b12,dpright:b13,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:+a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:-a2,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
|
||||
03000000321500000003000000000000,Razer Hydra,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a2,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
|
||||
03000000f8270000bf0b000000000000,Razer Kishi,a:b6,b:b7,back:b16,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b18,leftshoulder:b12,leftstick:b19,lefttrigger:b14,leftx:a0,lefty:a1,rightshoulder:b13,rightstick:b20,righttrigger:b15,rightx:a3,righty:a4,start:b17,x:b9,y:b10,platform:Windows,
|
||||
03000000321500000204000000000000,Razer Panthera PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
|
||||
@@ -883,7 +884,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
|
||||
03000000c82d00003032000000010000,8BitDo Zero 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,rightx:a2,righty:a31,start:b11,x:b4,y:b3,platform:Mac OS X,
|
||||
03000000491900001904000001010000,Amazon Luna Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,misc1:b9,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b7,x:b2,y:b3,platform:Mac OS X,
|
||||
03000000710100001904000000010000,Amazon Luna Controller,a:b0,b:b1,back:b11,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b9,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Mac OS X,
|
||||
0300000008100000e501000019040000,Anbernic Gamepad,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a4,start:b11,x:b4,y:b3,platform:Mac OS X,
|
||||
0300000008100000e501000019040000,Anbernic Handheld,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a4,start:b11,x:b4,y:b3,platform:Mac OS X,
|
||||
03000000373500004610000001000000,Anbernic RG P01,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b15,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X,
|
||||
03000000a30c00002700000003030000,Astro City Mini,a:b2,b:b1,back:b8,dpdown:+a4,dpleft:-a3,dpright:+a3,dpup:-a4,rightshoulder:b4,righttrigger:b5,start:b9,x:b3,y:b0,platform:Mac OS X,
|
||||
03000000a30c00002800000003030000,Astro City Mini,a:b2,b:b1,back:b8,leftx:a3,lefty:a4,rightshoulder:b4,righttrigger:b5,start:b9,x:b3,y:b0,platform:Mac OS X,
|
||||
@@ -1208,10 +1209,9 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
|
||||
05000000491900000204000021000000,Amazon Fire Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b17,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b12,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
|
||||
03000000491900001904000011010000,Amazon Luna Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,misc1:b9,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b7,x:b2,y:b3,platform:Linux,
|
||||
05000000710100001904000000010000,Amazon Luna Controller,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b11,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Linux,
|
||||
0300000008100000e501000001010000,Anbernic Gamepad,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a4,start:b11,x:b3,y:b4,platform:Linux,
|
||||
0300000008100000e501000001010000,Anbernic Handheld,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a4,start:b11,x:b3,y:b4,platform:Linux,
|
||||
03000000020500000913000010010000,Anbernic RG P01,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
|
||||
03000000373500000710000010010000,Anbernic RG P01,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
|
||||
030000005e0400008e02000072050000,Anbernic RG P01,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
|
||||
05000000373500004610000001000000,Anbernic RG P01,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b15,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
|
||||
03000000790000003018000011010000,Arcade Fightstick F300,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux,
|
||||
03000000a30c00002700000011010000,Astro City Mini,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,rightshoulder:b4,righttrigger:b5,start:b9,x:b3,y:b0,platform:Linux,
|
||||
@@ -1347,10 +1347,10 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
|
||||
03000000632500007505000011010000,Ipega PG 9099,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux,
|
||||
0500000049190000030400001b010000,Ipega PG9099,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
|
||||
05000000491900000204000000000000,Ipega PG9118,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
|
||||
03000000300f00001101000010010000,Jess Tech Colour Rumble Pad,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b1,platform:Linux,
|
||||
03000000300f00001001000010010000,Jess Tech Dual Analog Rumble,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b1,platform:Linux,
|
||||
03000000300f00000b01000010010000,Jess Tech GGE909 PC Recoil,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Linux,
|
||||
03000000ba2200002010000001010000,Jess Technology Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Linux,
|
||||
03000000300f00001101000010010000,Jess Tech Colour Rumble Pad,a:b2,b:b3,x:b0,y:b1,back:b8,start:b9,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b6,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a2,lefttrigger:b5,righttrigger:b7,platform:Linux,
|
||||
030000007e0500000620000001000000,Joy-Con (L),+leftx:h0.2,+lefty:h0.4,-leftx:h0.8,-lefty:h0.1,a:b0,b:b1,back:b13,leftshoulder:b4,leftstick:b10,rightshoulder:b5,start:b8,x:b2,y:b3,platform:Linux,
|
||||
050000007e0500000620000001000000,Joy-Con (L),+leftx:h0.2,+lefty:h0.4,-leftx:h0.8,-lefty:h0.1,a:b0,b:b1,back:b13,leftshoulder:b4,leftstick:b10,rightshoulder:b5,start:b8,x:b2,y:b3,platform:Linux,
|
||||
030000007e0500000720000001000000,Joy-Con (R),+leftx:h0.2,+lefty:h0.4,-leftx:h0.8,-lefty:h0.1,a:b0,b:b1,back:b12,leftshoulder:b4,leftstick:b11,rightshoulder:b5,start:b9,x:b2,y:b3,platform:Linux,
|
||||
@@ -1719,10 +1719,11 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
|
||||
030000006f0e00001503000000020000,Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
|
||||
030000005e0400008e02000000010000,Xbox 360 EasySMX,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
|
||||
030000005e040000a102000014010000,Xbox 360 Receiver,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b11,dpright:b12,dpup:b13,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
|
||||
0000000058626f782047616d65706100,Xbox Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a4,rightx:a2,righty:a3,start:b7,x:b2,y:b3,platform:Linux,
|
||||
030000005e0400000202000000010000,Xbox Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b5,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b2,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b3,y:b4,platform:Linux,
|
||||
030000005e0400008e02000072050000,Xbox Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
|
||||
030000006f0e00001304000000010000,Xbox Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
|
||||
03000000ffff0000ffff000000010000,Xbox Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b5,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b2,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b3,y:b4,platform:Linux,
|
||||
0000000058626f782047616d65706100,Xbox Gamepad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a4,rightx:a2,righty:a3,start:b7,x:b2,y:b3,platform:Linux,
|
||||
030000005e0400000a0b000005040000,Xbox One Controller,a:b1,b:b0,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b11,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b2,platform:Linux,
|
||||
030000005e040000d102000002010000,Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
|
||||
030000005e040000ea02000000000000,Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
|
||||
|
||||
@@ -1230,6 +1230,14 @@ size_t FileSystem::ReadFileWithProgress(std::FILE* fp, void* dst, size_t length,
|
||||
{
|
||||
progress->SetProgressRange(100);
|
||||
|
||||
return FileSystem::ReadFileWithPartialProgress(fp, dst, length, progress, 0, 100, error, chunk_size);
|
||||
}
|
||||
|
||||
size_t FileSystem::ReadFileWithPartialProgress(std::FILE* fp, void* dst, size_t length,
|
||||
ProgressCallback* progress, int startPercent, int endPercent, Error* error, size_t chunk_size)
|
||||
{
|
||||
const int deltaPercent = endPercent - startPercent;
|
||||
|
||||
size_t done = 0;
|
||||
while (done < length)
|
||||
{
|
||||
@@ -1243,7 +1251,7 @@ size_t FileSystem::ReadFileWithProgress(std::FILE* fp, void* dst, size_t length,
|
||||
break;
|
||||
}
|
||||
|
||||
progress->SetProgressValue((done * 100) / length);
|
||||
progress->SetProgressValue(startPercent + (done * deltaPercent) / length);
|
||||
done += read_size;
|
||||
}
|
||||
|
||||
|
||||
@@ -144,6 +144,8 @@ namespace FileSystem
|
||||
bool WriteStringToFile(const char* filename, const std::string_view sv);
|
||||
size_t ReadFileWithProgress(std::FILE* fp, void* dst, size_t length, ProgressCallback* progress,
|
||||
Error* error = nullptr, size_t chunk_size = 16 * 1024 * 1024);
|
||||
size_t ReadFileWithPartialProgress(std::FILE* fp, void* dst, size_t length, ProgressCallback* progress,
|
||||
int startPercent, int endPercent, Error* error = nullptr, size_t chunk_size = 16 * 1024 * 1024);
|
||||
|
||||
/// creates a directory in the local filesystem
|
||||
/// if the directory already exists, the return value will be true.
|
||||
|
||||
@@ -52,10 +52,10 @@
|
||||
|
||||
<!-- MSVC automatically adds __AVX__ and __AVX2__ appropriately -->
|
||||
<PreprocessorDefinitions Condition="'$(Platform)'=='x64'">_M_X86;__SSE4_1__;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<EnableEnhancedInstructionSet Condition="!$(Configuration.Contains(AVX2)) Or $(Configuration.Contains(Clang))">NotSet</EnableEnhancedInstructionSet>
|
||||
<EnableEnhancedInstructionSet Condition="$(Configuration.Contains(AVX2)) And !$(Configuration.Contains(Clang))">AdvancedVectorExtensions2</EnableEnhancedInstructionSet>
|
||||
<EnableEnhancedInstructionSet Condition="'$(Platform)'=='ARM64' Or !$(Configuration.Contains(AVX2))">NotSet</EnableEnhancedInstructionSet>
|
||||
<EnableEnhancedInstructionSet Condition="'$(Platform)'=='x64' And $(Configuration.Contains(AVX2))">AdvancedVectorExtensions2</EnableEnhancedInstructionSet>
|
||||
<!-- Allow SSE4 intrinsics on non-AVX Clang-cl builds -->
|
||||
<AdditionalOptions Condition="'$(Platform)'=='x64' And $(Configuration.Contains(Clang)) And !$(Configuration.Contains(AVX2))"> -march=nehalem %(AdditionalOptions)</AdditionalOptions>
|
||||
<AdditionalOptions Condition="'$(Platform)'=='x64' And $(Configuration.Contains(Clang)) And $(Configuration.Contains(AVX2))"> -march=haswell %(AdditionalOptions)</AdditionalOptions>
|
||||
<AdditionalOptions Condition="'$(Platform)'=='ARM64' And $(Configuration.Contains(Clang))"> -march=armv8.4-a %(AdditionalOptions)</AdditionalOptions>
|
||||
<AdditionalOptions Condition="!$(Configuration.Contains(Clang))">%(AdditionalOptions) /Zc:externConstexpr /Zc:__cplusplus /Zo /utf-8</AdditionalOptions>
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -21,6 +21,7 @@ static std::vector<std::pair<std::string, chd_header>> s_chd_hash_cache; // <fil
|
||||
static std::recursive_mutex s_chd_hash_cache_mutex;
|
||||
|
||||
// Provides an implementation of core_file which allows us to control if the underlying FILE handle is freed.
|
||||
// Additionally, this class allows greater control and feedback while precaching CHD files.
|
||||
// The lifetime of ChdCoreFileWrapper will be equal to that of the relevant chd_file,
|
||||
// ChdCoreFileWrapper will also get destroyed if chd_open_core_file fails.
|
||||
class ChdCoreFileWrapper
|
||||
@@ -31,10 +32,15 @@ private:
|
||||
core_file m_core;
|
||||
std::FILE* m_file;
|
||||
bool m_free_file = false;
|
||||
ChdCoreFileWrapper* m_parent = nullptr;
|
||||
std::unique_ptr<u8[]> m_file_cache;
|
||||
s64 m_file_cache_size;
|
||||
s64 m_file_cache_pos;
|
||||
|
||||
public:
|
||||
ChdCoreFileWrapper(std::FILE* file)
|
||||
ChdCoreFileWrapper(std::FILE* file, ChdCoreFileWrapper* parent)
|
||||
: m_file{file}
|
||||
, m_parent{parent}
|
||||
{
|
||||
m_core.argp = this;
|
||||
m_core.fsize = FSize;
|
||||
@@ -45,7 +51,7 @@ public:
|
||||
|
||||
~ChdCoreFileWrapper()
|
||||
{
|
||||
if (m_free_file)
|
||||
if (m_free_file && m_file)
|
||||
std::fclose(m_file);
|
||||
}
|
||||
|
||||
@@ -64,15 +70,100 @@ public:
|
||||
m_free_file = isOwner;
|
||||
}
|
||||
|
||||
s64 GetPrecacheSize()
|
||||
{
|
||||
const s64 size = static_cast<size_t>(FileSystem::FSize64(m_file));
|
||||
if (m_parent != nullptr)
|
||||
return m_parent->GetPrecacheSize() + size;
|
||||
else
|
||||
return size;
|
||||
}
|
||||
|
||||
bool Precache(ProgressCallback* progress, Error* error)
|
||||
{
|
||||
progress->SetProgressRange(100);
|
||||
|
||||
const s64 size = GetPrecacheSize();
|
||||
return PrecacheInternal(progress, error, 0, size);
|
||||
}
|
||||
|
||||
private:
|
||||
bool PrecacheInternal(ProgressCallback* progress, Error* error, s64 startSize, s64 finalSize)
|
||||
{
|
||||
m_file_cache_size = FileSystem::FSize64(m_file);
|
||||
if (m_file_cache_size <= 0)
|
||||
{
|
||||
Error::SetStringView(error, "Failed to determine file size.");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Copy the current file position.
|
||||
m_file_cache_pos = FileSystem::FTell64(m_file);
|
||||
if (m_file_cache_pos <= 0)
|
||||
{
|
||||
Error::SetStringView(error, "Failed to determine file position.");
|
||||
return false;
|
||||
}
|
||||
|
||||
m_file_cache = std::make_unique_for_overwrite<u8[]>(m_file_cache_size);
|
||||
if (FileSystem::FSeek64(m_file, 0, SEEK_SET) != 0 ||
|
||||
FileSystem::ReadFileWithPartialProgress(
|
||||
m_file, m_file_cache.get(), m_file_cache_size, progress,
|
||||
(startSize * 100) / finalSize,
|
||||
((startSize + m_file_cache_size) * 100) / finalSize,
|
||||
error) != static_cast<size_t>(m_file_cache_size))
|
||||
{
|
||||
m_file_cache.reset();
|
||||
// Precache failed, continue using file
|
||||
// Restore file position incase it's used for subsequent reads
|
||||
FileSystem::FSeek64(m_file, m_file_cache_pos, SEEK_SET);
|
||||
Error::SetStringView(error, "Failed to read part of the file.");
|
||||
return false;
|
||||
}
|
||||
|
||||
startSize += m_file_cache_size;
|
||||
|
||||
if (m_parent)
|
||||
{
|
||||
if (!m_parent->PrecacheInternal(progress, error, startSize, finalSize))
|
||||
{
|
||||
// Precache failed, continue using file
|
||||
// Restore file position incase it's used for subsequent reads
|
||||
FileSystem::FSeek64(m_file, m_file_cache_pos, SEEK_SET);
|
||||
m_file_cache.reset();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (m_free_file)
|
||||
std::fclose(m_file);
|
||||
m_file = nullptr;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static u64 FSize(core_file* file)
|
||||
{
|
||||
return static_cast<u64>(FileSystem::FSize64(FromCoreFile(file)->m_file));
|
||||
ChdCoreFileWrapper* fileWrapper = FromCoreFile(file);
|
||||
if (fileWrapper->m_file_cache)
|
||||
return fileWrapper->m_file_cache_size;
|
||||
else
|
||||
return static_cast<u64>(FileSystem::FSize64(fileWrapper->m_file));
|
||||
}
|
||||
|
||||
static size_t FRead(void* buffer, size_t elmSize, size_t elmCount, core_file* file)
|
||||
{
|
||||
return std::fread(buffer, elmSize, elmCount, FromCoreFile(file)->m_file);
|
||||
ChdCoreFileWrapper* fileWrapper = FromCoreFile(file);
|
||||
if (fileWrapper->m_file_cache)
|
||||
{
|
||||
// While currently libchdr only uses an elmCount of 1, we can't guarantee that will always be the case.
|
||||
elmCount = std::min<size_t>(elmCount, std::max<s64>(fileWrapper->m_file_cache_size - fileWrapper->m_file_cache_pos, 0) / elmSize);
|
||||
const size_t size = elmSize * elmCount;
|
||||
std::memcpy(buffer, &fileWrapper->m_file_cache[fileWrapper->m_file_cache_pos], size);
|
||||
return elmCount;
|
||||
}
|
||||
else
|
||||
return std::fread(buffer, elmSize, elmCount, fileWrapper->m_file);
|
||||
}
|
||||
|
||||
static int FClose(core_file* file)
|
||||
@@ -84,7 +175,28 @@ private:
|
||||
|
||||
static int FSeek(core_file* file, int64_t offset, int whence)
|
||||
{
|
||||
return FileSystem::FSeek64(FromCoreFile(file)->m_file, offset, whence);
|
||||
ChdCoreFileWrapper* fileWrapper = FromCoreFile(file);
|
||||
if (fileWrapper->m_file_cache)
|
||||
{
|
||||
switch (whence)
|
||||
{
|
||||
case SEEK_SET:
|
||||
fileWrapper->m_file_cache_pos = offset;
|
||||
break;
|
||||
case SEEK_CUR:
|
||||
fileWrapper->m_file_cache_pos += offset;
|
||||
break;
|
||||
case SEEK_END:
|
||||
fileWrapper->m_file_cache_pos = fileWrapper->m_file_cache_size + offset;
|
||||
break;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
return FileSystem::FSeek64(fileWrapper->m_file, offset, whence);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -95,10 +207,34 @@ ChdFileReader::~ChdFileReader()
|
||||
pxAssert(!ChdFile);
|
||||
}
|
||||
|
||||
static bool IsHeaderParentCHD(const chd_header& header, const chd_header& parent_header)
|
||||
{
|
||||
static const u8 nullmd5[CHD_MD5_BYTES]{};
|
||||
static const u8 nullsha1[CHD_SHA1_BYTES]{};
|
||||
|
||||
// Check MD5 if it isn't empty.
|
||||
if (std::memcmp(nullmd5, header.parentmd5, CHD_MD5_BYTES) != 0 &&
|
||||
std::memcmp(nullmd5, parent_header.md5, CHD_MD5_BYTES) != 0 &&
|
||||
std::memcmp(parent_header.md5, header.parentmd5, CHD_MD5_BYTES) != 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check SHA1 if it isn't empty.
|
||||
if (std::memcmp(nullsha1, header.parentsha1, CHD_SHA1_BYTES) != 0 &&
|
||||
std::memcmp(nullsha1, parent_header.sha1, CHD_SHA1_BYTES) != 0 &&
|
||||
std::memcmp(parent_header.sha1, header.parentsha1, CHD_SHA1_BYTES) != 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static chd_file* OpenCHD(const std::string& filename, FileSystem::ManagedCFilePtr fp, Error* error, u32 recursion_level)
|
||||
{
|
||||
chd_file* chd;
|
||||
ChdCoreFileWrapper* core_wrapper = new ChdCoreFileWrapper(fp.get());
|
||||
ChdCoreFileWrapper* core_wrapper = new ChdCoreFileWrapper(fp.get(), nullptr);
|
||||
// libchdr will take ownership of core_wrapper, and will close/free it on failure.
|
||||
chd_error err = chd_open_core_file(core_wrapper->GetCoreFile(), CHD_OPEN_READ, nullptr, &chd);
|
||||
if (err == CHDERR_NONE)
|
||||
@@ -144,14 +280,14 @@ static chd_file* OpenCHD(const std::string& filename, FileSystem::ManagedCFilePt
|
||||
if (!StringUtil::compareNoCase(parent_dir, Path::GetDirectory(it->first)))
|
||||
continue;
|
||||
|
||||
if (!chd_is_matching_parent(&header, &it->second))
|
||||
if (!IsHeaderParentCHD(header, it->second))
|
||||
continue;
|
||||
|
||||
// Re-check the header, it might have changed since we last opened.
|
||||
chd_header parent_header;
|
||||
auto parent_fp = FileSystem::OpenManagedSharedCFile(it->first.c_str(), "rb", FileSystem::FileShareMode::DenyWrite);
|
||||
if (parent_fp && chd_read_header_file(parent_fp.get(), &parent_header) == CHDERR_NONE &&
|
||||
chd_is_matching_parent(&header, &parent_header))
|
||||
IsHeaderParentCHD(header, parent_header))
|
||||
{
|
||||
// Need to take a copy of the string, because the parent might add to the list and invalidate the iterator.
|
||||
const std::string filename_to_open = it->first;
|
||||
@@ -192,7 +328,7 @@ static chd_file* OpenCHD(const std::string& filename, FileSystem::ManagedCFilePt
|
||||
else
|
||||
s_chd_hash_cache.emplace_back(fd.FileName, parent_header);
|
||||
|
||||
if (!chd_is_matching_parent(&header, &parent_header))
|
||||
if (!IsHeaderParentCHD(header, parent_header))
|
||||
continue;
|
||||
|
||||
// Match! Open this one.
|
||||
@@ -212,7 +348,7 @@ static chd_file* OpenCHD(const std::string& filename, FileSystem::ManagedCFilePt
|
||||
}
|
||||
|
||||
// Our last core file wrapper got freed, so make a new one.
|
||||
core_wrapper = new ChdCoreFileWrapper(fp.get());
|
||||
core_wrapper = new ChdCoreFileWrapper(fp.get(), ChdCoreFileWrapper::FromCoreFile(chd_core_file(parent_chd)));
|
||||
// Now try re-opening with the parent.
|
||||
err = chd_open_core_file(core_wrapper->GetCoreFile(), CHD_OPEN_READ, parent_chd, &chd);
|
||||
if (err != CHDERR_NONE)
|
||||
@@ -266,28 +402,11 @@ bool ChdFileReader::Open2(std::string filename, Error* error)
|
||||
|
||||
bool ChdFileReader::Precache2(ProgressCallback* progress, Error* error)
|
||||
{
|
||||
if (!CheckAvailableMemoryForPrecaching(chd_get_compressed_size(ChdFile), error))
|
||||
ChdCoreFileWrapper* fileWrapper = ChdCoreFileWrapper::FromCoreFile(chd_core_file(ChdFile));
|
||||
if (!CheckAvailableMemoryForPrecaching(fileWrapper->GetPrecacheSize(), error))
|
||||
return false;
|
||||
|
||||
progress->SetProgressRange(100);
|
||||
|
||||
const auto callback = [](size_t pos, size_t total, void* param) -> bool {
|
||||
ProgressCallback* progress = static_cast<ProgressCallback*>(param);
|
||||
const u32 percent = static_cast<u32>((pos * 100) / total);
|
||||
progress->SetProgressValue(std::min<u32>(percent, 100));
|
||||
return !progress->IsCancelled();
|
||||
};
|
||||
|
||||
const chd_error cerror = chd_precache_progress(ChdFile, callback, progress);
|
||||
if (cerror != CHDERR_NONE)
|
||||
{
|
||||
if (cerror != CHDERR_CANCELLED)
|
||||
Error::SetStringView(error, "Failed to read part of the file.");
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
return fileWrapper->Precache(progress, error);
|
||||
}
|
||||
|
||||
ThreadedFileReader::Chunk ChdFileReader::ChunkForOffset(u64 offset)
|
||||
|
||||
177
pcsx2/COP0.cpp
177
pcsx2/COP0.cpp
@@ -230,49 +230,49 @@ void MapTLB(const tlbs& t, int i)
|
||||
u32 saddr, eaddr;
|
||||
|
||||
COP0_LOG("MAP TLB %d: 0x%08X-> [0x%08X 0x%08X] S=%d G=%d ASID=%d Mask=0x%03X EntryLo0 PFN=%x EntryLo0 Cache=%x EntryLo1 PFN=%x EntryLo1 Cache=%x VPN2=%x",
|
||||
i, t.VPN2, t.PFN0, t.PFN1, t.S >> 31, t.G, t.ASID,
|
||||
t.Mask, t.EntryLo0 >> 6, (t.EntryLo0 & 0x38) >> 3, t.EntryLo1 >> 6, (t.EntryLo1 & 0x38) >> 3, t.VPN2);
|
||||
i, t.VPN2(), t.PFN0(), t.PFN1(), t.isSPR() >> 31, t.isGlobal(), t.EntryHi.ASID,
|
||||
t.Mask(), t.EntryLo0.PFN, t.EntryLo0.C, t.EntryLo1.PFN, t.EntryLo1.C, t.VPN2());
|
||||
|
||||
// According to the manual
|
||||
// 'It [SPR] must be mapped into a contiguous 16 KB of virtual address space that is
|
||||
// aligned on a 16KB boundary.Results are not guaranteed if this restriction is not followed.'
|
||||
// Assume that the game isn't doing anything less-than-ideal with the scratchpad mapping and map it directly to eeMem->Scratch.
|
||||
if (t.S)
|
||||
if (t.isSPR())
|
||||
{
|
||||
if (t.VPN2 != 0x70000000)
|
||||
Console.Warning("COP0: Mapping Scratchpad to non-default address 0x%08X", t.VPN2);
|
||||
if (t.VPN2() != 0x70000000)
|
||||
Console.Warning("COP0: Mapping Scratchpad to non-default address 0x%08X", t.VPN2());
|
||||
|
||||
vtlb_VMapBuffer(t.VPN2, eeMem->Scratch, Ps2MemSize::Scratch);
|
||||
vtlb_VMapBuffer(t.VPN2(), eeMem->Scratch, Ps2MemSize::Scratch);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (t.EntryLo0 & 0x2)
|
||||
if (t.EntryLo0.V)
|
||||
{
|
||||
mask = ((~t.Mask) << 1) & 0xfffff;
|
||||
saddr = t.VPN2 >> 12;
|
||||
eaddr = saddr + t.Mask + 1;
|
||||
mask = ((~t.Mask()) << 1) & 0xfffff;
|
||||
saddr = t.VPN2() >> 12;
|
||||
eaddr = saddr + t.Mask() + 1;
|
||||
|
||||
for (addr = saddr; addr < eaddr; addr++)
|
||||
{
|
||||
if ((addr & mask) == ((t.VPN2 >> 12) & mask))
|
||||
if ((addr & mask) == ((t.VPN2() >> 12) & mask))
|
||||
{ //match
|
||||
memSetPageAddr(addr << 12, t.PFN0 + ((addr - saddr) << 12));
|
||||
memSetPageAddr(addr << 12, t.PFN0() + ((addr - saddr) << 12));
|
||||
Cpu->Clear(addr << 12, 0x400);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (t.EntryLo1 & 0x2)
|
||||
if (t.EntryLo1.V)
|
||||
{
|
||||
mask = ((~t.Mask) << 1) & 0xfffff;
|
||||
saddr = (t.VPN2 >> 12) + t.Mask + 1;
|
||||
eaddr = saddr + t.Mask + 1;
|
||||
mask = ((~t.Mask()) << 1) & 0xfffff;
|
||||
saddr = (t.VPN2() >> 12) + t.Mask() + 1;
|
||||
eaddr = saddr + t.Mask() + 1;
|
||||
|
||||
for (addr = saddr; addr < eaddr; addr++)
|
||||
{
|
||||
if ((addr & mask) == ((t.VPN2 >> 12) & mask))
|
||||
if ((addr & mask) == ((t.VPN2() >> 12) & mask))
|
||||
{ //match
|
||||
memSetPageAddr(addr << 12, t.PFN1 + ((addr - saddr) << 12));
|
||||
memSetPageAddr(addr << 12, t.PFN1() + ((addr - saddr) << 12));
|
||||
Cpu->Clear(addr << 12, 0x400);
|
||||
}
|
||||
}
|
||||
@@ -280,27 +280,36 @@ void MapTLB(const tlbs& t, int i)
|
||||
}
|
||||
}
|
||||
|
||||
__inline u32 ConvertPageMask(const u32 PageMask)
|
||||
{
|
||||
const u32 mask = std::popcount(PageMask >> 13);
|
||||
|
||||
pxAssertMsg(!((mask & 1) || mask > 12), "Invalid page mask for this TLB entry. EE cache doesn't know what to do here.");
|
||||
|
||||
return (1 << (12 + mask)) - 1;
|
||||
}
|
||||
|
||||
void UnmapTLB(const tlbs& t, int i)
|
||||
{
|
||||
//Console.WriteLn("Clear TLB %d: %08x-> [%08x %08x] S=%d G=%d ASID=%d Mask= %03X", i,t.VPN2,t.PFN0,t.PFN1,t.S,t.G,t.ASID,t.Mask);
|
||||
u32 mask, addr;
|
||||
u32 saddr, eaddr;
|
||||
|
||||
if (t.S)
|
||||
if (t.isSPR())
|
||||
{
|
||||
vtlb_VMapUnmap(t.VPN2, 0x4000);
|
||||
vtlb_VMapUnmap(t.VPN2(), 0x4000);
|
||||
return;
|
||||
}
|
||||
|
||||
if (t.EntryLo0 & 0x2)
|
||||
if (t.EntryLo0.V)
|
||||
{
|
||||
mask = ((~t.Mask) << 1) & 0xfffff;
|
||||
saddr = t.VPN2 >> 12;
|
||||
eaddr = saddr + t.Mask + 1;
|
||||
mask = ((~t.Mask()) << 1) & 0xfffff;
|
||||
saddr = t.VPN2() >> 12;
|
||||
eaddr = saddr + t.Mask() + 1;
|
||||
// Console.WriteLn("Clear TLB: %08x ~ %08x",saddr,eaddr-1);
|
||||
for (addr = saddr; addr < eaddr; addr++)
|
||||
{
|
||||
if ((addr & mask) == ((t.VPN2 >> 12) & mask))
|
||||
if ((addr & mask) == ((t.VPN2() >> 12) & mask))
|
||||
{ //match
|
||||
memClearPageAddr(addr << 12);
|
||||
Cpu->Clear(addr << 12, 0x400);
|
||||
@@ -308,38 +317,74 @@ void UnmapTLB(const tlbs& t, int i)
|
||||
}
|
||||
}
|
||||
|
||||
if (t.EntryLo1 & 0x2)
|
||||
if (t.EntryLo1.V)
|
||||
{
|
||||
mask = ((~t.Mask) << 1) & 0xfffff;
|
||||
saddr = (t.VPN2 >> 12) + t.Mask + 1;
|
||||
eaddr = saddr + t.Mask + 1;
|
||||
mask = ((~t.Mask()) << 1) & 0xfffff;
|
||||
saddr = (t.VPN2() >> 12) + t.Mask() + 1;
|
||||
eaddr = saddr + t.Mask() + 1;
|
||||
// Console.WriteLn("Clear TLB: %08x ~ %08x",saddr,eaddr-1);
|
||||
for (addr = saddr; addr < eaddr; addr++)
|
||||
{
|
||||
if ((addr & mask) == ((t.VPN2 >> 12) & mask))
|
||||
if ((addr & mask) == ((t.VPN2() >> 12) & mask))
|
||||
{ //match
|
||||
memClearPageAddr(addr << 12);
|
||||
Cpu->Clear(addr << 12, 0x400);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < cachedTlbs.count; i++)
|
||||
{
|
||||
if (cachedTlbs.PFN0s[i] == t.PFN0() && cachedTlbs.PFN1s[i] == t.PFN1() && cachedTlbs.PageMasks[i] == ConvertPageMask(t.PageMask.UL))
|
||||
{
|
||||
for (size_t j = i; j < cachedTlbs.count - 1; j++)
|
||||
{
|
||||
cachedTlbs.CacheEnabled0[j] = cachedTlbs.CacheEnabled0[j + 1];
|
||||
cachedTlbs.CacheEnabled1[j] = cachedTlbs.CacheEnabled1[j + 1];
|
||||
cachedTlbs.PFN0s[j] = cachedTlbs.PFN0s[j + 1];
|
||||
cachedTlbs.PFN1s[j] = cachedTlbs.PFN1s[j + 1];
|
||||
cachedTlbs.PageMasks[j] = cachedTlbs.PageMasks[j + 1];
|
||||
}
|
||||
cachedTlbs.count--;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void WriteTLB(int i)
|
||||
{
|
||||
tlb[i].PageMask = cpuRegs.CP0.n.PageMask;
|
||||
tlb[i].EntryHi = cpuRegs.CP0.n.EntryHi;
|
||||
tlb[i].EntryLo0 = cpuRegs.CP0.n.EntryLo0;
|
||||
tlb[i].EntryLo1 = cpuRegs.CP0.n.EntryLo1;
|
||||
tlb[i].PageMask.UL = cpuRegs.CP0.n.PageMask;
|
||||
tlb[i].EntryHi.UL = cpuRegs.CP0.n.EntryHi;
|
||||
tlb[i].EntryLo0.UL = cpuRegs.CP0.n.EntryLo0;
|
||||
tlb[i].EntryLo1.UL = cpuRegs.CP0.n.EntryLo1;
|
||||
|
||||
tlb[i].Mask = (cpuRegs.CP0.n.PageMask >> 13) & 0xfff;
|
||||
tlb[i].nMask = (~tlb[i].Mask) & 0xfff;
|
||||
tlb[i].VPN2 = ((cpuRegs.CP0.n.EntryHi >> 13) & (~tlb[i].Mask)) << 13;
|
||||
tlb[i].ASID = cpuRegs.CP0.n.EntryHi & 0xfff;
|
||||
tlb[i].G = cpuRegs.CP0.n.EntryLo0 & cpuRegs.CP0.n.EntryLo1 & 0x1;
|
||||
tlb[i].PFN0 = (((cpuRegs.CP0.n.EntryLo0 >> 6) & 0xFFFFF) & (~tlb[i].Mask)) << 12;
|
||||
tlb[i].PFN1 = (((cpuRegs.CP0.n.EntryLo1 >> 6) & 0xFFFFF) & (~tlb[i].Mask)) << 12;
|
||||
tlb[i].S = cpuRegs.CP0.n.EntryLo0 & 0x80000000;
|
||||
// Setting the cache mode to reserved values is vaguely defined in the manual.
|
||||
// I found that SPR is set to cached regardless.
|
||||
// Non-SPR entries default to uncached on reserved cache modes.
|
||||
if (tlb[i].isSPR())
|
||||
{
|
||||
tlb[i].EntryLo0.C = 3;
|
||||
tlb[i].EntryLo1.C = 3;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!tlb[i].EntryLo0.isValidCacheMode())
|
||||
tlb[i].EntryLo0.C = 2;
|
||||
if (!tlb[i].EntryLo1.isValidCacheMode())
|
||||
tlb[i].EntryLo1.C = 2;
|
||||
}
|
||||
|
||||
if (!tlb[i].isSPR() && ((tlb[i].EntryLo0.V && tlb[i].EntryLo0.isCached()) || (tlb[i].EntryLo1.V && tlb[i].EntryLo1.isCached())))
|
||||
{
|
||||
const size_t idx = cachedTlbs.count;
|
||||
cachedTlbs.CacheEnabled0[idx] = tlb[i].EntryLo0.isCached() ? ~0 : 0;
|
||||
cachedTlbs.CacheEnabled1[idx] = tlb[i].EntryLo1.isCached() ? ~0 : 0;
|
||||
cachedTlbs.PFN1s[idx] = tlb[i].PFN1();
|
||||
cachedTlbs.PFN0s[idx] = tlb[i].PFN0();
|
||||
cachedTlbs.PageMasks[idx] = ConvertPageMask(tlb[i].PageMask.UL);
|
||||
|
||||
cachedTlbs.count++;
|
||||
}
|
||||
|
||||
MapTLB(tlb[i], i);
|
||||
}
|
||||
@@ -355,49 +400,57 @@ namespace COP0 {
|
||||
cpuRegs.CP0.n.Index, cpuRegs.CP0.n.PageMask, cpuRegs.CP0.n.EntryHi,
|
||||
cpuRegs.CP0.n.EntryLo0, cpuRegs.CP0.n.EntryLo1);
|
||||
|
||||
int i = cpuRegs.CP0.n.Index & 0x3f;
|
||||
const u8 i = cpuRegs.CP0.n.Index & 0x3f;
|
||||
|
||||
cpuRegs.CP0.n.PageMask = tlb[i].PageMask;
|
||||
cpuRegs.CP0.n.EntryHi = tlb[i].EntryHi & ~(tlb[i].PageMask | 0x1f00);
|
||||
cpuRegs.CP0.n.EntryLo0 = (tlb[i].EntryLo0 & ~1) | ((tlb[i].EntryHi >> 12) & 1);
|
||||
cpuRegs.CP0.n.EntryLo1 = (tlb[i].EntryLo1 & ~1) | ((tlb[i].EntryHi >> 12) & 1);
|
||||
if (i > 47)
|
||||
{
|
||||
Console.Warning("TLBR with index > 47! (%d)", i);
|
||||
return;
|
||||
}
|
||||
|
||||
cpuRegs.CP0.n.PageMask = tlb[i].PageMask.Mask << 13;
|
||||
cpuRegs.CP0.n.EntryHi = tlb[i].EntryHi.UL & ~((tlb[i].PageMask.Mask << 13) | 0x1f00);
|
||||
cpuRegs.CP0.n.EntryLo0 = tlb[i].EntryLo0.UL & ~(0xFC000000) & ~1;
|
||||
cpuRegs.CP0.n.EntryLo1 = tlb[i].EntryLo1.UL & ~(0x7C000000) & ~1;
|
||||
// "If both the Global bit of EntryLo0 and EntryLo1 are set to 1, the processor ignores the ASID during TLB lookup."
|
||||
// This is reflected during TLBR, where G is only set if both EntryLo0 and EntryLo1 are global.
|
||||
cpuRegs.CP0.n.EntryLo0 |= (tlb[i].EntryLo0.UL & 1) & (tlb[i].EntryLo1.UL & 1);
|
||||
cpuRegs.CP0.n.EntryLo1 |= (tlb[i].EntryLo0.UL & 1) & (tlb[i].EntryLo1.UL & 1);
|
||||
}
|
||||
|
||||
void TLBWI()
|
||||
{
|
||||
int j = cpuRegs.CP0.n.Index & 0x3f;
|
||||
const u8 j = cpuRegs.CP0.n.Index & 0x3f;
|
||||
|
||||
//if (j > 48) return;
|
||||
if (j > 47)
|
||||
{
|
||||
Console.Warning("TLBWI with index > 47! (%d)", j);
|
||||
return;
|
||||
}
|
||||
|
||||
COP0_LOG("COP0_TLBWI %d:%x,%x,%x,%x",
|
||||
cpuRegs.CP0.n.Index, cpuRegs.CP0.n.PageMask, cpuRegs.CP0.n.EntryHi,
|
||||
cpuRegs.CP0.n.EntryLo0, cpuRegs.CP0.n.EntryLo1);
|
||||
|
||||
UnmapTLB(tlb[j], j);
|
||||
tlb[j].PageMask = cpuRegs.CP0.n.PageMask;
|
||||
tlb[j].EntryHi = cpuRegs.CP0.n.EntryHi;
|
||||
tlb[j].EntryLo0 = cpuRegs.CP0.n.EntryLo0;
|
||||
tlb[j].EntryLo1 = cpuRegs.CP0.n.EntryLo1;
|
||||
WriteTLB(j);
|
||||
}
|
||||
|
||||
void TLBWR()
|
||||
{
|
||||
int j = cpuRegs.CP0.n.Random & 0x3f;
|
||||
const u8 j = cpuRegs.CP0.n.Random & 0x3f;
|
||||
|
||||
//if (j > 48) return;
|
||||
if (j > 47)
|
||||
{
|
||||
Console.Warning("TLBWR with random > 47! (%d)", j);
|
||||
return;
|
||||
}
|
||||
|
||||
DevCon.Warning("COP0_TLBWR %d:%x,%x,%x,%x\n",
|
||||
cpuRegs.CP0.n.Random, cpuRegs.CP0.n.PageMask, cpuRegs.CP0.n.EntryHi,
|
||||
cpuRegs.CP0.n.EntryLo0, cpuRegs.CP0.n.EntryLo1);
|
||||
|
||||
//if (j > 48) return;
|
||||
|
||||
UnmapTLB(tlb[j], j);
|
||||
tlb[j].PageMask = cpuRegs.CP0.n.PageMask;
|
||||
tlb[j].EntryHi = cpuRegs.CP0.n.EntryHi;
|
||||
tlb[j].EntryLo0 = cpuRegs.CP0.n.EntryLo0;
|
||||
tlb[j].EntryLo1 = cpuRegs.CP0.n.EntryLo1;
|
||||
WriteTLB(j);
|
||||
}
|
||||
|
||||
@@ -422,7 +475,7 @@ namespace COP0 {
|
||||
cpuRegs.CP0.n.Index = 0xFFFFFFFF;
|
||||
for (i = 0; i < 48; i++)
|
||||
{
|
||||
if (tlb[i].VPN2 == ((~tlb[i].Mask) & (EntryHi32.s.VPN2)) && ((tlb[i].G & 1) || ((tlb[i].ASID & 0xff) == EntryHi32.s.ASID)))
|
||||
if (tlb[i].VPN2() == ((~tlb[i].Mask()) & (EntryHi32.s.VPN2)) && ((tlb[i].isGlobal()) || ((tlb[i].EntryHi.ASID & 0xff) == EntryHi32.s.ASID)))
|
||||
{
|
||||
cpuRegs.CP0.n.Index = i;
|
||||
break;
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#include <atomic>
|
||||
#include <thread>
|
||||
#include <functional>
|
||||
#include <mutex>
|
||||
#include <shared_mutex>
|
||||
|
||||
#include <ccc/ast.h>
|
||||
|
||||
@@ -7050,10 +7050,6 @@ TRANSLATE_NOOP("FullscreenUI", "Increases or decreases the virtual picture size
|
||||
TRANSLATE_NOOP("FullscreenUI", "Crop");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Crops the image, while respecting aspect ratio.");
|
||||
TRANSLATE_NOOP("FullscreenUI", "%dpx");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Enable Widescreen Patches");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Enables loading widescreen patches from pnach files.");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Enable No-Interlacing Patches");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Enables loading no-interlacing patches from pnach files.");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Bilinear Upscaling");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Smooths out the image when upscaling the console to the screen.");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Integer Upscaling");
|
||||
|
||||
@@ -852,8 +852,16 @@ namespace R3000A
|
||||
|
||||
v0 = file->read(buf.get(), count);
|
||||
|
||||
for (s32 i = 0; i < (s32)v0; i++)
|
||||
iopMemWrite8(data + i, buf[i]);
|
||||
[[likely]]
|
||||
if (v0 >= 0 && iopMemSafeWriteBytes(data, buf.get(), v0))
|
||||
{
|
||||
psxCpu->Clear(data, (v0 + 3) / 4);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (s32 i = 0; i < static_cast<s32>(v0); i++)
|
||||
iopMemWrite8(data + i, buf[i]);
|
||||
}
|
||||
|
||||
pc = ra;
|
||||
return 1;
|
||||
@@ -899,8 +907,12 @@ namespace R3000A
|
||||
{
|
||||
auto buf = std::make_unique<char[]>(count);
|
||||
|
||||
for (u32 i = 0; i < count; i++)
|
||||
buf[i] = iopMemRead8(data + i);
|
||||
[[unlikely]]
|
||||
if (!iopMemSafeReadBytes(data, buf.get(), count))
|
||||
{
|
||||
for (u32 i = 0; i < count; i++)
|
||||
buf[i] = iopMemRead8(data + i);
|
||||
}
|
||||
|
||||
v0 = file->write(buf.get(), count);
|
||||
|
||||
|
||||
@@ -36,6 +36,8 @@ u32 EEoCycle;
|
||||
|
||||
alignas(16) cpuRegistersPack _cpuRegistersPack;
|
||||
alignas(16) tlbs tlb[48];
|
||||
cachedTlbs_t cachedTlbs;
|
||||
|
||||
R5900cpu *Cpu = NULL;
|
||||
|
||||
static constexpr uint eeWaitCycles = 3072;
|
||||
@@ -59,6 +61,7 @@ void cpuReset()
|
||||
std::memset(&cpuRegs, 0, sizeof(cpuRegs));
|
||||
std::memset(&fpuRegs, 0, sizeof(fpuRegs));
|
||||
std::memset(&tlb, 0, sizeof(tlb));
|
||||
cachedTlbs.count = 0;
|
||||
|
||||
cpuRegs.pc = 0xbfc00000; //set pc reg to stack
|
||||
cpuRegs.CP0.n.Config = 0x440;
|
||||
|
||||
@@ -5,6 +5,8 @@
|
||||
|
||||
#include "common/Pcsx2Defs.h"
|
||||
|
||||
#include <array>
|
||||
|
||||
// --------------------------------------------------------------------------------------
|
||||
// EE Bios function name tables.
|
||||
// --------------------------------------------------------------------------------------
|
||||
@@ -160,17 +162,68 @@ struct fpuRegisters {
|
||||
u32 ACCflag; // an internal accumulator overflow flag
|
||||
};
|
||||
|
||||
union PageMask_t
|
||||
{
|
||||
struct
|
||||
{
|
||||
u32 : 13;
|
||||
u32 Mask : 12;
|
||||
u32 : 7;
|
||||
};
|
||||
u32 UL;
|
||||
};
|
||||
|
||||
union EntryHi_t
|
||||
{
|
||||
struct
|
||||
{
|
||||
u32 ASID:8;
|
||||
u32 : 5;
|
||||
u32 VPN2:19;
|
||||
};
|
||||
u32 UL;
|
||||
};
|
||||
|
||||
union EntryLo_t
|
||||
{
|
||||
struct
|
||||
{
|
||||
u32 G:1;
|
||||
u32 V:1;
|
||||
u32 D:1;
|
||||
u32 C:3;
|
||||
u32 PFN:20;
|
||||
u32 : 5;
|
||||
u32 S : 1; // Only used in EntryLo0
|
||||
};
|
||||
u32 UL;
|
||||
|
||||
constexpr bool isCached() const { return C == 0x3; }
|
||||
constexpr bool isValidCacheMode() const { return C == 0x2 || C == 0x3 || C == 0x7; }
|
||||
};
|
||||
|
||||
struct tlbs
|
||||
{
|
||||
u32 PageMask,EntryHi;
|
||||
u32 EntryLo0,EntryLo1;
|
||||
u32 Mask, nMask;
|
||||
u32 G;
|
||||
u32 ASID;
|
||||
u32 VPN2;
|
||||
u32 PFN0;
|
||||
u32 PFN1;
|
||||
u32 S;
|
||||
PageMask_t PageMask;
|
||||
EntryHi_t EntryHi;
|
||||
EntryLo_t EntryLo0;
|
||||
EntryLo_t EntryLo1;
|
||||
|
||||
// (((cpuRegs.CP0.n.EntryLo0 >> 6) & 0xFFFFF) & (~tlb[i].Mask())) << 12;
|
||||
constexpr u32 PFN0() const { return (EntryLo0.PFN & ~Mask()) << 12; }
|
||||
constexpr u32 PFN1() const { return (EntryLo1.PFN & ~Mask()) << 12; }
|
||||
constexpr u32 VPN2() const {return ((EntryHi.VPN2) & (~Mask())) << 13; }
|
||||
constexpr u32 Mask() const { return PageMask.Mask; }
|
||||
constexpr bool isGlobal() const { return EntryLo0.G && EntryLo1.G; }
|
||||
constexpr bool isSPR() const { return EntryLo0.S; }
|
||||
|
||||
constexpr bool operator==(const tlbs& other) const
|
||||
{
|
||||
return PageMask.UL == other.PageMask.UL &&
|
||||
EntryHi.UL == other.EntryHi.UL &&
|
||||
EntryLo0.UL == other.EntryLo0.UL &&
|
||||
EntryLo1.UL == other.EntryLo1.UL;
|
||||
}
|
||||
};
|
||||
|
||||
#ifndef _PC_
|
||||
@@ -211,6 +264,19 @@ struct cpuRegistersPack
|
||||
alignas(16) extern cpuRegistersPack _cpuRegistersPack;
|
||||
alignas(16) extern tlbs tlb[48];
|
||||
|
||||
struct cachedTlbs_t
|
||||
{
|
||||
u32 count;
|
||||
|
||||
alignas(16) std::array<u32, 48> PageMasks;
|
||||
alignas(16) std::array<u32, 48> PFN1s;
|
||||
alignas(16) std::array<u32, 48> CacheEnabled1;
|
||||
alignas(16) std::array<u32, 48> PFN0s;
|
||||
alignas(16) std::array<u32, 48> CacheEnabled0;
|
||||
};
|
||||
|
||||
extern cachedTlbs_t cachedTlbs;
|
||||
|
||||
static cpuRegisters& cpuRegs = _cpuRegistersPack.cpuRegs;
|
||||
static fpuRegisters& fpuRegs = _cpuRegistersPack.fpuRegs;
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
|
||||
#include "SIO/SioTypes.h"
|
||||
#include "SIO/Memcard/MemoryCardProtocol.h"
|
||||
#include "Counters.h"
|
||||
|
||||
#include "Host.h"
|
||||
#include "IconsPromptFont.h"
|
||||
@@ -128,6 +129,8 @@ void AutoEject::ClearAll()
|
||||
// unsafe to shutdown the VM due to memcard access.
|
||||
static std::atomic_uint32_t currentBusyTicks = 0;
|
||||
|
||||
uint32_t sioLastFrameMcdBusy = 0;
|
||||
|
||||
void MemcardBusy::Decrement()
|
||||
{
|
||||
if (currentBusyTicks.load(std::memory_order_relaxed) == 0)
|
||||
@@ -139,6 +142,7 @@ void MemcardBusy::Decrement()
|
||||
void MemcardBusy::SetBusy()
|
||||
{
|
||||
currentBusyTicks.store(300, std::memory_order_release);
|
||||
sioLastFrameMcdBusy = g_FrameCount;
|
||||
}
|
||||
|
||||
bool MemcardBusy::IsBusy()
|
||||
@@ -149,4 +153,15 @@ bool MemcardBusy::IsBusy()
|
||||
void MemcardBusy::ClearBusy()
|
||||
{
|
||||
currentBusyTicks.store(0, std::memory_order_release);
|
||||
sioLastFrameMcdBusy = 0;
|
||||
}
|
||||
|
||||
#include "common/Console.h"
|
||||
void MemcardBusy::CheckSaveStateDependency()
|
||||
{
|
||||
if (g_FrameCount - sioLastFrameMcdBusy > NUM_FRAMES_BEFORE_SAVESTATE_DEPENDENCY_WARNING)
|
||||
{
|
||||
Host::AddIconOSDMessage("MemcardBusy", ICON_PF_MEMORY_CARD,
|
||||
TRANSLATE_SV("MemoryCard", "The virtual console hasn't saved to your memory card for quite some time. Savestates should not be used in place of in-game saves."), Host::OSD_INFO_DURATION);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -118,10 +118,19 @@ namespace AutoEject
|
||||
extern void ClearAll();
|
||||
} // namespace AutoEject
|
||||
|
||||
// ~1 hour of memory card inactivity.
|
||||
constexpr u32 NUM_FRAMES_BEFORE_SAVESTATE_DEPENDENCY_WARNING = 60 * 60 * 60;
|
||||
|
||||
// Set to the current frame count when there is memory card activity.
|
||||
// Used to detect the last frame when memory card activity was detected,
|
||||
// and if it exceeds a certain threshold, warns on savestate save/load.
|
||||
extern uint32_t sioLastFrameMcdBusy;
|
||||
|
||||
namespace MemcardBusy
|
||||
{
|
||||
extern void Decrement();
|
||||
extern void SetBusy();
|
||||
extern bool IsBusy();
|
||||
extern void ClearBusy();
|
||||
extern void CheckSaveStateDependency();
|
||||
}
|
||||
|
||||
@@ -541,5 +541,6 @@ bool Sio2::DoState(StateWrapper& sw)
|
||||
}
|
||||
}
|
||||
|
||||
sw.Do(&sioLastFrameMcdBusy);
|
||||
return sw.IsGood();
|
||||
}
|
||||
|
||||
@@ -15,12 +15,13 @@
|
||||
#include "Host.h"
|
||||
#include "MTGS.h"
|
||||
#include "MTVU.h"
|
||||
#include "SIO/Pad/Pad.h"
|
||||
#include "Patch.h"
|
||||
#include "R3000A.h"
|
||||
#include "SIO/Multitap/MultitapProtocol.h"
|
||||
#include "SIO/Pad/Pad.h"
|
||||
#include "SIO/Sio.h"
|
||||
#include "SIO/Sio0.h"
|
||||
#include "SIO/Sio2.h"
|
||||
#include "SIO/Multitap/MultitapProtocol.h"
|
||||
#include "SPU2/spu2.h"
|
||||
#include "SaveState.h"
|
||||
#include "StateWrapper.h"
|
||||
@@ -182,6 +183,7 @@ bool SaveStateBase::FreezeInternals(Error* error)
|
||||
Freeze(psxRegs); // iop regs
|
||||
Freeze(fpuRegs);
|
||||
Freeze(tlb); // tlbs
|
||||
Freeze(cachedTlbs); // cached tlbs
|
||||
Freeze(AllowParams1); //OSDConfig written (Fast Boot)
|
||||
Freeze(AllowParams2);
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@ enum class FreezeAction
|
||||
// [SAVEVERSION+]
|
||||
// This informs the auto updater that the users savestates will be invalidated.
|
||||
|
||||
static const u32 g_SaveVersion = (0x9A51 << 16) | 0x0000;
|
||||
static const u32 g_SaveVersion = (0x9A53 << 16) | 0x0000;
|
||||
|
||||
|
||||
// the freezing data between submodules and core
|
||||
|
||||
@@ -1818,6 +1818,7 @@ bool VMManager::DoLoadState(const char* filename)
|
||||
MTGS::PresentCurrentFrame();
|
||||
}
|
||||
|
||||
MemcardBusy::CheckSaveStateDependency();
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1866,6 +1867,7 @@ bool VMManager::DoSaveState(const char* filename, s32 slot_for_message, bool zip
|
||||
}
|
||||
|
||||
Host::OnSaveStateSaved(filename);
|
||||
MemcardBusy::CheckSaveStateDependency();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
#include "fmt/core.h"
|
||||
|
||||
#include <bit>
|
||||
#include <immintrin.h>
|
||||
#include <map>
|
||||
#include <unordered_set>
|
||||
#include <unordered_map>
|
||||
@@ -109,46 +110,77 @@ vtlb_private::VTLBVirtual::VTLBVirtual(VTLBPhysical phys, u32 paddr, u32 vaddr)
|
||||
}
|
||||
}
|
||||
|
||||
__inline int ConvertPageMask(u32 PageMask)
|
||||
{
|
||||
const u32 mask = std::popcount(PageMask >> 13);
|
||||
|
||||
pxAssertMsg(!((mask & 1) || mask > 12), "Invalid page mask for this TLB entry. EE cache doesn't know what to do here.");
|
||||
|
||||
return (1 << (12 + mask)) - 1;
|
||||
}
|
||||
|
||||
__inline int CheckCache(u32 addr)
|
||||
{
|
||||
u32 mask;
|
||||
|
||||
// Check if the cache is enabled
|
||||
if (((cpuRegs.CP0.n.Config >> 16) & 0x1) == 0)
|
||||
{
|
||||
//DevCon.Warning("Data Cache Disabled! %x", cpuRegs.CP0.n.Config);
|
||||
return false; //
|
||||
return false;
|
||||
}
|
||||
|
||||
for (int i = 1; i < 48; i++)
|
||||
const size_t size = cachedTlbs.count;
|
||||
const int stride = 4;
|
||||
|
||||
__m128i addr_vec = _mm_set1_epi32(addr);
|
||||
|
||||
size_t i = 0;
|
||||
|
||||
for (; i + stride <= size; i += stride)
|
||||
{
|
||||
if (((tlb[i].EntryLo1 & 0x38) >> 3) == 0x3)
|
||||
const __m128i pfn1_vec = _mm_loadu_si128(reinterpret_cast<const __m128i*>(&cachedTlbs.PFN1s[i]));
|
||||
const __m128i pfn0_vec = _mm_loadu_si128(reinterpret_cast<const __m128i*>(&cachedTlbs.PFN0s[i]));
|
||||
const __m128i mask_vec = _mm_loadu_si128(reinterpret_cast<const __m128i*>(&cachedTlbs.PageMasks[i]));
|
||||
|
||||
const __m128i cached1_vec = _mm_loadu_si128(reinterpret_cast<const __m128i*>(&cachedTlbs.CacheEnabled1[i]));
|
||||
const __m128i cached0_vec = _mm_loadu_si128(reinterpret_cast<const __m128i*>(&cachedTlbs.CacheEnabled0[i]));
|
||||
|
||||
const __m128i pfn1_end_vec = _mm_add_epi32(pfn1_vec, mask_vec);
|
||||
const __m128i pfn0_end_vec = _mm_add_epi32(pfn0_vec, mask_vec);
|
||||
|
||||
// pfn0 <= addr
|
||||
const __m128i gteLowerBound0 = _mm_or_si128(
|
||||
_mm_cmpgt_epi32(addr_vec, pfn0_vec),
|
||||
_mm_cmpeq_epi32(addr_vec, pfn0_vec));
|
||||
// pfn0 + mask >= addr
|
||||
const __m128i gteUpperBound0 = _mm_or_si128(
|
||||
_mm_cmpgt_epi32(pfn0_end_vec, addr_vec),
|
||||
_mm_cmpeq_epi32(pfn0_end_vec, addr_vec));
|
||||
|
||||
// pfn1 <= addr
|
||||
const __m128i gteUpperBound1 = _mm_or_si128(
|
||||
_mm_cmpgt_epi32(pfn1_end_vec, addr_vec),
|
||||
_mm_cmpeq_epi32(pfn1_end_vec, addr_vec));
|
||||
// pfn1 + mask >= addr
|
||||
const __m128i gteLowerBound1 = _mm_or_si128(
|
||||
_mm_cmpgt_epi32(addr_vec, pfn1_vec),
|
||||
_mm_cmpeq_epi32(addr_vec, pfn1_vec));
|
||||
|
||||
// pfn0 <= addr <= pfn0 + mask
|
||||
__m128i cmp0 = _mm_and_si128(gteLowerBound0, gteUpperBound0);
|
||||
// pfn1 <= addr <= pfn1 + mask
|
||||
__m128i cmp1 = _mm_and_si128(gteLowerBound1, gteUpperBound1);
|
||||
|
||||
cmp1 = _mm_and_si128(cmp1, cached1_vec);
|
||||
cmp0 = _mm_and_si128(cmp0, cached0_vec);
|
||||
|
||||
const __m128i cmp = _mm_or_si128(cmp1, cmp0);
|
||||
|
||||
if (!_mm_testz_si128(cmp, cmp))
|
||||
{
|
||||
mask = ConvertPageMask(tlb[i].PageMask);
|
||||
if ((addr >= tlb[i].PFN1) && (addr <= tlb[i].PFN1 + mask))
|
||||
{
|
||||
//DevCon.Warning("Yay! Cache check cache addr=%x, mask=%x, addr+mask=%x, VPN2=%x PFN0=%x", addr, mask, (addr & mask), tlb[i].VPN2, tlb[i].PFN0);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (((tlb[i].EntryLo0 & 0x38) >> 3) == 0x3)
|
||||
{
|
||||
mask = ConvertPageMask(tlb[i].PageMask);
|
||||
if ((addr >= tlb[i].PFN0) && (addr <= tlb[i].PFN0 + mask))
|
||||
{
|
||||
//DevCon.Warning("Yay! Cache check cache addr=%x, mask=%x, addr+mask=%x, VPN2=%x PFN0=%x", addr, mask, (addr & mask), tlb[i].VPN2, tlb[i].PFN0);
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
for (; i < size; i++)
|
||||
{
|
||||
const u32 mask = cachedTlbs.PageMasks[i];
|
||||
if ((cachedTlbs.CacheEnabled1[i] && addr >= cachedTlbs.PFN1s[i] && addr <= cachedTlbs.PFN1s[i] + mask) ||
|
||||
(cachedTlbs.CacheEnabled0[i] && addr >= cachedTlbs.PFN0s[i] && addr <= cachedTlbs.PFN0s[i] + mask))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
// --------------------------------------------------------------------------------------
|
||||
|
||||
Reference in New Issue
Block a user