Compare commits

...

13 Commits

Author SHA1 Message Date
Hallkezz
c6d0f5e3cd GameDB: Change recommended blending level 2 to 4 for Twisted Metal: Head-On [Extra Twisted Edition]. (#12107)
Fixes menu text brightness in Twisted Metal: Head-On [Extra Twisted Edition].
2024-12-22 13:03:40 +01:00
PCSX2 Bot
34c9590cf1 [ci skip] Qt: Update Base Translation. 2024-12-18 19:06:27 -05:00
Ty Lamontagne
a2c7542e48 Savestates: Warn on savestate load and saves without mcd activity
[SAVEVERSION+]
2024-12-18 18:01:30 -05:00
TheLastRar
72a9f18456 3rdparty: Sync libchdr to commit cb077337d53392454e7100a0fd07139ca678e527 2024-12-18 17:58:44 -05:00
TheLastRar
7f59757eea 3rdparty/libchdr: Purge almost all remaining patches
Leaving only the chd_read_header_* functions, of which exists an equivalent in later libchdr versions
2024-12-18 17:58:44 -05:00
TheLastRar
3b89020082 3rdparty/libchdr: Purge now unused patches 2024-12-18 16:23:49 -05:00
TheLastRar
a7b07eb53f ChdReader: Use core_file to implement precaching 2024-12-18 16:23:49 -05:00
TheLastRar
58d13dac34 FileSystem: Add ReadFileWithPartialProgress for multiple files 2024-12-18 16:23:49 -05:00
Ty Lamontagne
5a8921dd22 IOPBios: Defer to iopMemSafeReadBytes when HLEing writes 2024-12-18 16:15:07 -05:00
Ty Lamontagne
f964dfaa5e IOPBios: Defer to iopMemSafeWriteBytes when HLEing reads 2024-12-18 16:15:07 -05:00
PCSX2 Bot
17274eb397 [ci skip] Qt: Update Base Translation. 2024-12-17 20:54:52 -05:00
TheLastRar
2f0b00a7a1 ChdFileReader: Migrate libchdr patch into PCSX2
Added function didn't need to be in libchdr
2024-12-17 13:35:10 -05:00
Mrlinkwii
260380abec CI: disable builds on controller database update 2024-12-17 19:22:03 +01:00
21 changed files with 2245 additions and 2045 deletions

View File

@@ -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."

View File

@@ -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__ */

View File

@@ -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
}

View File

@@ -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);
}

View File

@@ -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

View File

@@ -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
/***************************************************************************

File diff suppressed because it is too large Load Diff

View File

@@ -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;
}

View File

@@ -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:

View File

@@ -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;
}

View File

@@ -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

View File

@@ -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)

View File

@@ -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");

View File

@@ -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);

View File

@@ -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);
}
}

View File

@@ -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();
}

View File

@@ -541,5 +541,6 @@ bool Sio2::DoState(StateWrapper& sw)
}
}
sw.Do(&sioLastFrameMcdBusy);
return sw.IsGood();
}

View File

@@ -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"

View File

@@ -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

View File

@@ -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;
}