mirror of
https://github.com/PCSX2/pcsx2.git
synced 2026-01-31 01:15:24 +01:00
Compare commits
13 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
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."
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -12419,7 +12419,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:
|
||||
|
||||
@@ -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.
|
||||
|
||||
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)
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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 = (0x9A52 << 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;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user