Sync with non-wide

This commit is contained in:
ds22x 2024-07-08 23:30:31 +02:00
parent 5474f11328
commit 7d56f9f304
32 changed files with 12550 additions and 9308 deletions

1
.gitignore vendored
View File

@ -14,6 +14,7 @@ sdl/build_sdl2
/libretro/msvc/msvc-2017/msvc-2017.vcxproj.user
genesis_plus_gx_libretro.*
genesis_plus_gx_wide_libretro.*
*.o
*.a

View File

@ -10,7 +10,7 @@ addons:
- ubuntu-toolchain-r-test
env:
global:
- CORE=genesis_plus_gx_wide
- CORE=genesis_plus_gx
- COMPILER_NAME=gcc CXX=g++-7 CC=gcc-7
matrix:
- PLATFORM=3ds

View File

@ -58,9 +58,10 @@ Genesis Plus GX 1.7.5 (xx/xx/xxxx) (Eke-Eke)
* fixed byte access to font data registers
* fixed memory mode register bits masking when read from MAIN-CPU and SUB-CPU (verified on real hardware, cf. Krikzz's mcd-verificator)
* fixed pending level 1 interrupts when GFX interrupt is disabled (fixes random freezes when exiting "Batman Returns" option menu)
* fixed CDD seek command again (Final Fight CD freeze with model 2 BIOS)
* fixed CDD seek command again (fixes Final Fight CD freeze with model 2 BIOS)
* fixed CDD status reported during seek/access time (fixes sound effect synchronization issue in Bari Arm)
* fixed CDD position reset when disc is stopped (fixes random freezes in Spiderman vs Kingpin when switching between audio tracks)
* fixed CDD seeking start delay (fixes Radical Rex incorrect PRG-RAM & Word-RAM initialization, causing missing sprites during intro) */
* fixed word access to CDD control register (fixes spurious audio track playback on startup with Mode 1 patched games using MSU-MD driver)
* fixed CD communication registers state on peripheral reset (fixes SUB-CPU side initialization in MSU-MD sample demo and some Mode 1 patched games using MSU-MD driver)
* fixed 32x32 pixels stamp index masking during GFX operation (fixes graphics rotation/scaling effects in "Chuck Rock II - Son of Chuck")
@ -75,7 +76,8 @@ Genesis Plus GX 1.7.5 (xx/xx/xxxx) (Eke-Eke)
* added support for Everdrive extended SSF mapper
* added support for MegaSD CD hardware overlay (MD+ hacks) and extended SSF2 / ROM write mappers
* added emulation of Z80 halt when accessing 68k bus during DMA from 68k bus
* added basic emulation of 68k bus access refresh delays (fixes Super Airwolf graphical glitch during intro & some Krikzz's mcd-verificator timing tests)
* added emulation of 68k delay during Z80 acccess to 68k bus
* added (basic) emulation of 68k bus refresh delays (fixes Super Airwolf graphical glitch during intro & some Krikzz's mcd-verificator timing tests)
* added (very basic) emulation of Flashkit MD hardware
* added emulation of Micro Machines USA on-board TMSS bypass logic hardware
* added SRAM support for games larger than 8MB

View File

@ -245,7 +245,7 @@ else ifneq (,$(findstring ios,$(platform)))
SHARED := -dynamiclib
ENDIANNESS_DEFINES := -DLSB_FIRST -DBYTE_ORDER=LITTLE_ENDIAN
PLATFORM_DEFINES := -DHAVE_ZLIB
MAX_ROM_SIZE = 16777216
MAX_ROM_SIZE = 33554432
MINVERSION :=
ifeq ($(IOSSDK),)
@ -280,6 +280,7 @@ else ifeq ($(platform), tvos-arm64)
CC = cc -arch arm64 -isysroot $(IOSSDK)
CXX = c++ -arch arm64 -isysroot $(IOSSDK)
MAX_ROM_SIZE = 33554432
# Theos
else ifeq ($(platform), theos_ios)

View File

@ -2,7 +2,7 @@
* Genesis Plus
* Mega Drive cartridge hardware support
*
* Copyright (C) 2007-2023 Eke-Eke (Genesis Plus GX)
* Copyright (C) 2007-2024 Eke-Eke (Genesis Plus GX)
*
* Many cartridge protections were initially documented by Haze
* (http://haze.mameworld.info/)
@ -465,7 +465,10 @@ void md_cart_init(void)
memset(&cart.hw, 0, sizeof(cart.hw));
/* initialize default $200000-$20ffff mapping (for games using SRAM & ROM bankswitching) */
cart.hw.regs[0] = (0x200000 & cart.mask) >> 16;
if (m68k.memory_map[0x20].base == sram.sram)
{
cart.hw.regs[0] = (0x200000 & cart.mask) >> 16;
}
/* search for game into database */
for (i=0; i<(sizeof(rom_database)/sizeof(md_entry_t)); i++)

View File

@ -2,7 +2,7 @@
* Genesis Plus
* Mega Drive cartridge hardware support
*
* Copyright (C) 2007-2023 Eke-Eke (Genesis Plus GX)
* Copyright (C) 2007-2024 Eke-Eke (Genesis Plus GX)
*
* Most cartridge protections were initially documented by Haze
* (http://haze.mameworld.info/)

View File

@ -397,6 +397,16 @@ int cdd_load(char *filename, char *header)
return -1;
}
#ifdef __LIBRETRO__
if (config.cd_precache)
{
log_cb(RETRO_LOG_INFO, "Pre-caching \"%s\" ...\n", filename);
if (chd_precache(cdd.chd.file) != CHDERR_NONE)
return -1;
log_cb(RETRO_LOG_INFO, "Pre-cache done.\n");
}
#endif
/* retrieve CHD header */
head = chd_get_header(cdd.chd.file);
@ -1936,6 +1946,79 @@ void cdd_update(void)
/* udpate current track index */
cdd.index = index;
}
/* seeking should start with at least one interrupt delay (fixes Radical Rex incorrect PRG-RAM & Word-RAM initialization, causing missing sprites during intro) */
if (scd.regs[0x38>>1].byte.h == CD_SEEK)
{
/* reset track index */
int index = 0;
/* new LBA position */
int lba = ((scd.regs[0x44>>1].byte.h * 10 + scd.regs[0x44>>1].byte.l) * 60 +
(scd.regs[0x46>>1].byte.h * 10 + scd.regs[0x46>>1].byte.l)) * 75 +
(scd.regs[0x48>>1].byte.h * 10 + scd.regs[0x48>>1].byte.l) - 150;
/* CD drive latency */
if (!cdd.latency)
{
/* Fixes a few games hanging because they expect data to be read with some delay */
/* Wolf Team games (Annet Futatabi, Aisle Lord, Cobra Command, Earnest Evans, Road Avenger & Time Gal) need at least 11 interrupts delay */
/* Space Adventure Cobra (2nd morgue scene) needs at least 13 interrupts delay (incl. seek time, so 11 is OK) */
/* By default, at least two interrupts latency is required by current emulation model (BIOS hangs otherwise) */
cdd.latency = 2 + 9*config.cd_latency;
}
/* CD drive seek time */
/* max. seek time = 1.5 s = 1.5 x 75 = 112.5 CDD interrupts (rounded to 120) for 270000 sectors max on disc. */
/* Note: This is only a rough approximation since, on real hardware, seek time is much likely not linear and */
/* latency much larger than above value, but this model works fine for Sonic CD (track 26 playback needs to */
/* be enough delayed to start in sync with intro sequence, as compared with real hardware recording). */
/* It also works fine for Switch/Panic! intro (at least 30 interrupts are needed while seeking from 00:05:63 */
/* to 24:03:19 in Switch or when seeking from 00:05:60 to 24:06:07 in Panic!). */
if (lba > cdd.lba)
{
cdd.latency += (((lba - cdd.lba) * 120 * config.cd_latency) / 270000);
}
else
{
cdd.latency += (((cdd.lba - lba) * 120 * config.cd_latency) / 270000);
}
/* update current LBA */
cdd.lba = lba;
/* get track index */
while ((cdd.toc.tracks[index].end <= lba) && (index < cdd.toc.last))
index++;
/* audio track ? */
if (cdd.toc.tracks[index].type == TYPE_AUDIO)
{
/* stay within track limits when seeking files */
if (lba < cdd.toc.tracks[index].start)
{
lba = cdd.toc.tracks[index].start;
}
/* seek to current track sector */
cdd_seek_audio(index, lba);
}
/* update current track index */
cdd.index = index;
/* seek to current subcode position */
if (cdd.toc.sub)
{
cdStreamSeek(cdd.toc.sub, lba * 96, SEEK_SET);
}
/* no audio track playing (yet) */
scd.regs[0x36>>1].byte.h = 0x01;
/* update CDD status to either PLAY or PAUSE depending on host command (will be reported to host once seeking has ended) */
cdd.status = scd.regs[0x42>>1].byte.h & 0x05;
}
}
void cdd_process(void)
@ -2112,73 +2195,7 @@ void cdd_process(void)
case 0x03: /* Play */
{
/* reset track index */
int index = 0;
/* new LBA position */
int lba = ((scd.regs[0x44>>1].byte.h * 10 + scd.regs[0x44>>1].byte.l) * 60 +
(scd.regs[0x46>>1].byte.h * 10 + scd.regs[0x46>>1].byte.l)) * 75 +
(scd.regs[0x48>>1].byte.h * 10 + scd.regs[0x48>>1].byte.l) - 150;
/* CD drive latency */
if (!cdd.latency)
{
/* Fixes a few games hanging because they expect data to be read with some delay */
/* Wolf Team games (Annet Futatabi, Aisle Lord, Cobra Command, Earnest Evans, Road Avenger & Time Gal) need at least 11 interrupts delay */
/* Space Adventure Cobra (2nd morgue scene) needs at least 13 interrupts delay (incl. seek time, so 11 is OK) */
/* By default, at least two interrupts latency is required by current emulation model (BIOS hangs otherwise) */
cdd.latency = 2 + 9*config.cd_latency;
}
/* CD drive seek time */
/* max. seek time = 1.5 s = 1.5 x 75 = 112.5 CDD interrupts (rounded to 120) for 270000 sectors max on disc. */
/* Note: This is only a rough approximation since, on real hardware, seek time is much likely not linear and */
/* latency much larger than above value, but this model works fine for Sonic CD (track 26 playback needs to */
/* be enough delayed to start in sync with intro sequence, as compared with real hardware recording). */
if (lba > cdd.lba)
{
cdd.latency += (((lba - cdd.lba) * 120 * config.cd_latency) / 270000);
}
else
{
cdd.latency += (((cdd.lba - lba) * 120 * config.cd_latency) / 270000);
}
/* update current LBA */
cdd.lba = lba;
/* get track index */
while ((cdd.toc.tracks[index].end <= lba) && (index < cdd.toc.last)) index++;
/* audio track ? */
if (cdd.toc.tracks[index].type == TYPE_AUDIO)
{
/* stay within track limits when seeking files */
if (lba < cdd.toc.tracks[index].start)
{
lba = cdd.toc.tracks[index].start;
}
/* seek to current track sector */
cdd_seek_audio(index, lba);
}
/* update current track index */
cdd.index = index;
/* seek to current subcode position */
if (cdd.toc.sub)
{
cdStreamSeek(cdd.toc.sub, lba * 96, SEEK_SET);
}
/* no audio track playing (yet) */
scd.regs[0x36>>1].byte.h = 0x01;
/* update status (reported to host once seeking has ended) */
cdd.status = CD_PLAY;
/* RS0 should indicates seeking until drive is ready (fixes audio delay in Bari Arm) */
/* RS0 should indicate seeking until drive is ready (fixes audio delay in Bari Arm) */
/* RS1=0xf to invalidate track infos in RS2-RS8 until drive is ready (fixes Snatcher Act 2 start cutscene) */
scd.regs[0x38>>1].w = (CD_SEEK << 8) | 0x0f;
scd.regs[0x3a>>1].w = 0x0000;
@ -2190,61 +2207,6 @@ void cdd_process(void)
case 0x04: /* Seek */
{
/* reset track index */
int index = 0;
/* new LBA position */
int lba = ((scd.regs[0x44>>1].byte.h * 10 + scd.regs[0x44>>1].byte.l) * 60 +
(scd.regs[0x46>>1].byte.h * 10 + scd.regs[0x46>>1].byte.l)) * 75 +
(scd.regs[0x48>>1].byte.h * 10 + scd.regs[0x48>>1].byte.l) - 150;
/* CD drive seek time */
/* We are using similar linear model as above, although still not exactly accurate, */
/* it works fine for Switch/Panic! intro (Switch needs at least 30 interrupts while */
/* seeking from 00:05:63 to 24:03:19, Panic! when seeking from 00:05:60 to 24:06:07) */
if (lba > cdd.lba)
{
cdd.latency = ((lba - cdd.lba) * 120 * config.cd_latency) / 270000;
}
else
{
cdd.latency = ((cdd.lba - lba) * 120 * config.cd_latency) / 270000;
}
/* update current LBA */
cdd.lba = lba;
/* get current track index */
while ((cdd.toc.tracks[index].end <= lba) && (index < cdd.toc.last)) index++;
/* audio track ? */
if (cdd.toc.tracks[index].type == TYPE_AUDIO)
{
/* stay within track limits when seeking files */
if (lba < cdd.toc.tracks[index].start)
{
lba = cdd.toc.tracks[index].start;
}
/* seek to current track sector */
cdd_seek_audio(index, lba);
}
/* update current track index */
cdd.index = index;
/* seek to current subcode position */
if (cdd.toc.sub)
{
cdStreamSeek(cdd.toc.sub, lba * 96, SEEK_SET);
}
/* no audio track playing */
scd.regs[0x36>>1].byte.h = 0x01;
/* update status (reported to host once seeking has ended) */
cdd.status = CD_PAUSE;
/* RS1=0xf to invalidate track infos in RS2-RS8 while seeking (fixes Final Fight CD intro when seek time is emulated) */
scd.regs[0x38>>1].w = (CD_SEEK << 8) | 0x0f;
scd.regs[0x3a>>1].w = 0x0000;

View File

@ -1,7 +1,6 @@
/* license:BSD-3-Clause
* copyright-holders:Aaron Giles
*/
/***************************************************************************
* copyright-holders:Aaron Giles
***************************************************************************
bitstream.c
@ -9,8 +8,8 @@
***************************************************************************/
#include "bitstream.h"
#include <stdlib.h>
#include "bitstream.h"
/***************************************************************************
* INLINE FUNCTIONS
@ -108,9 +107,10 @@ uint32_t bitstream_read_offset(struct bitstream* bitstream)
}
//-------------------------------------------------
// flush - flush to the nearest byte
//-------------------------------------------------
/*-------------------------------------------------
* flush - flush to the nearest byte
*-------------------------------------------------
*/
uint32_t bitstream_flush(struct bitstream* bitstream)
{

View File

@ -1,6 +1,6 @@
/* license:BSD-3-Clause
* copyright-holders:Aaron Giles
***************************************************************************
***************************************************************************
bitstream.h

View File

@ -1,6 +1,6 @@
// license:BSD-3-Clause
// copyright-holders:Aaron Giles
/***************************************************************************
/* license:BSD-3-Clause
* copyright-holders:Aaron Giles
***************************************************************************
cdrom.c
@ -15,13 +15,13 @@
schemes will differ after track 1!
***************************************************************************/
#ifdef WANT_RAW_DATA_SECTOR
#include <assert.h>
#include <string.h>
#include "cdrom.h"
#ifdef WANT_RAW_DATA_SECTOR
/***************************************************************************
DEBUGGING
***************************************************************************/
@ -64,8 +64,6 @@ void CLIB_DECL logerror(const char *text, ...) ATTR_PRINTF(1,2);
#define LOG(x)
#endif
/***************************************************************************
CONSTANTS
***************************************************************************/
@ -92,8 +90,6 @@ void CLIB_DECL logerror(const char *text, ...) ATTR_PRINTF(1,2);
/** @brief 43 bytes each. */
#define ECC_Q_COMP 43
/**
* @brief -------------------------------------------------
* ECC lookup tables pre-calculated tables for ECC data calcs
@ -301,16 +297,16 @@ static const uint16_t qoffsets[ECC_Q_NUM_BYTES][ECC_Q_COMP] =
{ 0x867,0x003,0x05b,0x0b3,0x10b,0x163,0x1bb,0x213,0x26b,0x2c3,0x31b,0x373,0x3cb,0x423,0x47b,0x4d3,0x52b,0x583,0x5db,0x633,0x68b,0x6e3,0x73b,0x793,0x7eb,0x843,0x89b,0x037,0x08f,0x0e7,0x13f,0x197,0x1ef,0x247,0x29f,0x2f7,0x34f,0x3a7,0x3ff,0x457,0x4af,0x507,0x55f }
};
/*-------------------------------------------------
* ecc_source_byte - return data from the sector
* at the given offset, masking anything
* particular to a mode
*-------------------------------------------------
*/
//-------------------------------------------------
// ecc_source_byte - return data from the sector
// at the given offset, masking anything
// particular to a mode
//-------------------------------------------------
static inline uint8_t ecc_source_byte(const uint8_t *sector, uint32_t offset)
INLINE uint8_t ecc_source_byte(const uint8_t *sector, uint32_t offset)
{
// in mode 2 always treat these as 0 bytes
/* in mode 2 always treat these as 0 bytes */
return (sector[MODE_OFFSET] == 2 && offset < 4) ? 0x00 : sector[SYNC_OFFSET + SYNC_NUM_BYTES + offset];
}
@ -330,8 +326,9 @@ static inline uint8_t ecc_source_byte(const uint8_t *sector, uint32_t offset)
void ecc_compute_bytes(const uint8_t *sector, const uint16_t *row, int rowlen, uint8_t *val1, uint8_t *val2)
{
int component;
*val1 = *val2 = 0;
for (int component = 0; component < rowlen; component++)
for (component = 0; component < rowlen; component++)
{
*val1 ^= ecc_source_byte(sector, row[component]);
*val2 ^= ecc_source_byte(sector, row[component]);
@ -355,8 +352,9 @@ void ecc_compute_bytes(const uint8_t *sector, const uint16_t *row, int rowlen, u
int ecc_verify(const uint8_t *sector)
{
// first verify P bytes
for (int byte = 0; byte < ECC_P_NUM_BYTES; byte++)
int byte;
/* first verify P bytes */
for (byte = 0; byte < ECC_P_NUM_BYTES; byte++)
{
uint8_t val1, val2;
ecc_compute_bytes(sector, poffsets[byte], ECC_P_COMP, &val1, &val2);
@ -364,8 +362,8 @@ int ecc_verify(const uint8_t *sector)
return 0;
}
// then verify Q bytes
for (int byte = 0; byte < ECC_Q_NUM_BYTES; byte++)
/* then verify Q bytes */
for (byte = 0; byte < ECC_Q_NUM_BYTES; byte++)
{
uint8_t val1, val2;
ecc_compute_bytes(sector, qoffsets[byte], ECC_Q_COMP, &val1, &val2);
@ -388,12 +386,13 @@ int ecc_verify(const uint8_t *sector)
void ecc_generate(uint8_t *sector)
{
// first verify P bytes
for (int byte = 0; byte < ECC_P_NUM_BYTES; byte++)
int byte;
/* first verify P bytes */
for (byte = 0; byte < ECC_P_NUM_BYTES; byte++)
ecc_compute_bytes(sector, poffsets[byte], ECC_P_COMP, &sector[ECC_P_OFFSET + byte], &sector[ECC_P_OFFSET + ECC_P_NUM_BYTES + byte]);
// then verify Q bytes
for (int byte = 0; byte < ECC_Q_NUM_BYTES; byte++)
/* then verify Q bytes */
for (byte = 0; byte < ECC_Q_NUM_BYTES; byte++)
ecc_compute_bytes(sector, qoffsets[byte], ECC_Q_COMP, &sector[ECC_Q_OFFSET + byte], &sector[ECC_Q_OFFSET + ECC_Q_NUM_BYTES + byte]);
}

View File

@ -1,6 +1,6 @@
/* license:BSD-3-Clause */
/* copyright-holders:Aaron Giles */
/***************************************************************************
/* license:BSD-3-Clause
* copyright-holders:Aaron Giles
***************************************************************************
cdrom.h
@ -15,14 +15,12 @@
#include <stdint.h>
/***************************************************************************
CONSTANTS
***************************************************************************/
/* tracks are padded to a multiple of this many frames */
#define CD_TRACK_PADDING (4)
#define CD_TRACK_PADDING (4)
#define CD_MAX_TRACKS (99) /* AFAIK the theoretical limit */
#define CD_MAX_SECTOR_DATA (2352)
#define CD_MAX_SUBCODE_DATA (96)
@ -53,8 +51,8 @@ enum
CD_SUB_NONE /* no subcode data stored */
};
#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
#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 */
/***************************************************************************
FUNCTION PROTOTYPES
@ -67,4 +65,45 @@ void ecc_generate(uint8_t *sector);
void ecc_clear(uint8_t *sector);
#endif
/***************************************************************************
INLINE FUNCTIONS
***************************************************************************/
INLINE uint32_t msf_to_lba(uint32_t msf)
{
return ( ((msf&0x00ff0000)>>16) * 60 * 75) + (((msf&0x0000ff00)>>8) * 75) + ((msf&0x000000ff)>>0);
}
INLINE uint32_t lba_to_msf(uint32_t lba)
{
uint8_t m, s, f;
m = lba / (60 * 75);
lba -= m * (60 * 75);
s = lba / 75;
f = lba % 75;
return ((m / 10) << 20) | ((m % 10) << 16) |
((s / 10) << 12) | ((s % 10) << 8) |
((f / 10) << 4) | ((f % 10) << 0);
}
/**
* segacd needs it like this.. investigate
* Angelo also says PCE tracks often start playing at the
* wrong address.. related?
**/
INLINE uint32_t lba_to_msf_alt(int lba)
{
uint32_t ret = 0;
ret |= ((lba / (60 * 75))&0xff)<<16;
ret |= (((lba / 75) % 60)&0xff)<<8;
ret |= ((lba % 75)&0xff)<<0;
return ret;
}
#endif /* __CDROM_H__ */

File diff suppressed because it is too large Load Diff

View File

@ -48,7 +48,6 @@ extern "C" {
#include "coretypes.h"
/***************************************************************************
Compressed Hunks of Data header format. All numbers are stored in
@ -194,12 +193,21 @@ extern "C" {
#define CHDFLAGS_IS_WRITEABLE 0x00000002
#define CHDFLAGS_UNDEFINED 0xfffffffc
#define CHD_MAKE_TAG(a,b,c,d) (((a) << 24) | ((b) << 16) | ((c) << 8) | (d))
/* compression types */
#define CHDCOMPRESSION_NONE 0
#define CHDCOMPRESSION_ZLIB 1
#define CHDCOMPRESSION_ZLIB_PLUS 2
#define CHDCOMPRESSION_AV 3
#define CHD_CODEC_NONE 0
#define CHD_CODEC_ZLIB CHD_MAKE_TAG('z','l','i','b')
/* general codecs with CD frontend */
#define CHD_CODEC_CD_ZLIB CHD_MAKE_TAG('c','d','z','l')
#define CHD_CODEC_CD_LZMA CHD_MAKE_TAG('c','d','l','z')
#define CHD_CODEC_CD_FLAC CHD_MAKE_TAG('c','d','f','l')
/* A/V codec configuration parameters */
#define AV_CODEC_COMPRESS_CONFIG 1
#define AV_CODEC_DECOMPRESS_CONFIG 2
@ -212,33 +220,34 @@ extern "C" {
#define CHD_MDFLAGS_CHECKSUM 0x01 /* indicates data is checksummed */
/* standard hard disk metadata */
#define HARD_DISK_METADATA_TAG 0x47444444 /* 'GDDD' */
#define HARD_DISK_METADATA_TAG CHD_MAKE_TAG('G','D','D','D')
#define HARD_DISK_METADATA_FORMAT "CYLS:%d,HEADS:%d,SECS:%d,BPS:%d"
/* hard disk identify information */
#define HARD_DISK_IDENT_METADATA_TAG 0x49444e54 /* 'IDNT' */
#define HARD_DISK_IDENT_METADATA_TAG CHD_MAKE_TAG('I','D','N','T')
/* hard disk key information */
#define HARD_DISK_KEY_METADATA_TAG 0x4b455920 /* 'KEY ' */
#define HARD_DISK_KEY_METADATA_TAG CHD_MAKE_TAG('K','E','Y',' ')
/* pcmcia CIS information */
#define PCMCIA_CIS_METADATA_TAG 0x43495320 /* 'CIS ' */
#define PCMCIA_CIS_METADATA_TAG CHD_MAKE_TAG('C','I','S',' ')
/* standard CD-ROM metadata */
#define CDROM_OLD_METADATA_TAG 0x43484344 /* 'CHCD' */
#define CDROM_TRACK_METADATA_TAG 0x43485452 /* 'CHTR' */
#define CDROM_OLD_METADATA_TAG CHD_MAKE_TAG('C','H','C','D')
#define CDROM_TRACK_METADATA_TAG CHD_MAKE_TAG('C','H','T','R')
#define CDROM_TRACK_METADATA_FORMAT "TRACK:%d TYPE:%s SUBTYPE:%s FRAMES:%d"
#define CDROM_TRACK_METADATA2_TAG 0x43485432 /* 'CHT2' */
#define CDROM_TRACK_METADATA2_TAG CHD_MAKE_TAG('C','H','T','2')
#define CDROM_TRACK_METADATA2_FORMAT "TRACK:%d TYPE:%s SUBTYPE:%s FRAMES:%d PREGAP:%d PGTYPE:%s PGSUB:%s POSTGAP:%d"
#define GDROM_TRACK_METADATA_TAG 0x43484744 /* 'CHTD' */
#define GDROM_OLD_METADATA_TAG CHD_MAKE_TAG('C','H','G','T')
#define GDROM_TRACK_METADATA_TAG CHD_MAKE_TAG('C', 'H', 'G', 'D')
#define GDROM_TRACK_METADATA_FORMAT "TRACK:%d TYPE:%s SUBTYPE:%s FRAMES:%d PAD:%d PREGAP:%d PGTYPE:%s PGSUB:%s POSTGAP:%d"
/* standard A/V metadata */
#define AV_METADATA_TAG 0x41564156 /* 'AVAV' */
#define AV_METADATA_TAG CHD_MAKE_TAG('A','V','A','V')
#define AV_METADATA_FORMAT "FPS:%d.%06d WIDTH:%d HEIGHT:%d INTERLACED:%d CHANNELS:%d SAMPLERATE:%d"
/* A/V laserdisc frame metadata */
#define AV_LD_METADATA_TAG 0x41564C44 /* 'AVLD' */
#define AV_LD_METADATA_TAG CHD_MAKE_TAG('A','V','L','D')
/* CHD open values */
#define CHD_OPEN_READ 1
@ -305,9 +314,9 @@ struct _chd_header
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 */
UINT8 parentsha1[CHD_SHA1_BYTES]; /* overall SHA1 checksum of parent */
UINT32 unitbytes; /* TODO V5 */
UINT64 unitcount; /* TODO V5 */
UINT64 unitcount; /* TODO V5 */
UINT32 hunkcount; /* TODO V5 */
/* map information */
@ -337,6 +346,19 @@ struct _chd_verify_result
FUNCTION PROTOTYPES
***************************************************************************/
#ifdef _MSC_VER
#ifdef CHD_DLL
#ifdef CHD_DLL_EXPORTS
#define CHD_EXPORT __declspec(dllexport)
#else
#define CHD_EXPORT __declspec(dllimport)
#endif
#else
#define CHD_EXPORT
#endif
#else
#define CHD_EXPORT __attribute__ ((visibility("default")))
#endif
/* ----- CHD file management ----- */
@ -347,25 +369,27 @@ struct _chd_verify_result
/* chd_error chd_create_file(core_file *file, UINT64 logicalbytes, UINT32 hunkbytes, UINT32 compression, chd_file *parent); */
/* open an existing CHD file */
chd_error chd_open_file(core_file *file, int mode, chd_file *parent, chd_file **chd);
chd_error chd_open(const char *filename, int mode, chd_file *parent, chd_file **chd);
CHD_EXPORT chd_error chd_open_file(core_file *file, int mode, chd_file *parent, chd_file **chd);
CHD_EXPORT chd_error chd_open(const char *filename, int mode, chd_file *parent, chd_file **chd);
/* precache underlying file */
CHD_EXPORT chd_error chd_precache(chd_file *chd);
/* close a CHD file */
void chd_close(chd_file *chd);
CHD_EXPORT void chd_close(chd_file *chd);
/* return the associated core_file */
core_file *chd_core_file(chd_file *chd);
CHD_EXPORT core_file *chd_core_file(chd_file *chd);
/* return an error string for the given CHD error */
const char *chd_error_string(chd_error err);
CHD_EXPORT const char *chd_error_string(chd_error err);
/* ----- CHD header management ----- */
/* return a pointer to the extracted CHD header data */
const chd_header *chd_get_header(chd_file *chd);
CHD_EXPORT const chd_header *chd_get_header(chd_file *chd);
@ -373,14 +397,14 @@ const chd_header *chd_get_header(chd_file *chd);
/* ----- core data read/write ----- */
/* read one hunk from the CHD file */
chd_error chd_read(chd_file *chd, UINT32 hunknum, void *buffer);
CHD_EXPORT chd_error chd_read(chd_file *chd, UINT32 hunknum, void *buffer);
/* ----- metadata management ----- */
/* get indexed metadata of a particular sort */
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 searchtag, UINT32 searchindex, void *output, UINT32 outputlen, UINT32 *resultlen, UINT32 *resulttag, UINT8 *resultflags);
@ -388,10 +412,10 @@ chd_error chd_get_metadata(chd_file *chd, UINT32 searchtag, UINT32 searchindex,
/* ----- codec interfaces ----- */
/* set internal codec parameters */
chd_error chd_codec_config(chd_file *chd, int param, void *config);
CHD_EXPORT chd_error chd_codec_config(chd_file *chd, int param, void *config);
/* return a string description of a codec */
const char *chd_get_codec_name(UINT32 codec);
CHD_EXPORT const char *chd_get_codec_name(UINT32 codec);
#ifdef __cplusplus
}

View File

@ -1,6 +1,6 @@
// license:BSD-3-Clause
// copyright-holders:Aaron Giles
/***************************************************************************
/* license:BSD-3-Clause
* copyright-holders:Aaron Giles
***************************************************************************
flac.c
@ -10,28 +10,35 @@
#include <assert.h>
#include <string.h>
#include "flac.h"
#define DR_FLAC_IMPLEMENTATION
#include <dr_libs/dr_flac.h>
//**************************************************************************
// FLAC DECODER
//**************************************************************************
/***************************************************************************
* FLAC DECODER
***************************************************************************
*/
static FLAC__StreamDecoderReadStatus flac_decoder_read_callback_static(const FLAC__StreamDecoder *decoder, FLAC__byte buffer[], size_t *bytes, void *client_data);
FLAC__StreamDecoderReadStatus flac_decoder_read_callback(void* client_data, FLAC__byte buffer[], size_t *bytes);
static void flac_decoder_metadata_callback_static(const FLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data);
static FLAC__StreamDecoderTellStatus flac_decoder_tell_callback_static(const FLAC__StreamDecoder *decoder, FLAC__uint64 *absolute_byte_offset, void *client_data);
static FLAC__StreamDecoderWriteStatus flac_decoder_write_callback_static(const FLAC__StreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data);
FLAC__StreamDecoderWriteStatus flac_decoder_write_callback(void* client_data, const FLAC__Frame *frame, const FLAC__int32 * const buffer[]);
static void flac_decoder_error_callback_static(const FLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data);
static size_t flac_decoder_read_callback(void *userdata, void *buffer, size_t bytes);
static drflac_bool32 flac_decoder_seek_callback(void *userdata, int offset, drflac_seek_origin origin);
static void flac_decoder_metadata_callback(void *userdata, drflac_metadata *metadata);
static void flac_decoder_write_callback(void *userdata, void *buffer, size_t len);
/* getters (valid after reset) */
static uint32_t sample_rate(flac_decoder *decoder) { return decoder->sample_rate; }
static uint8_t channels(flac_decoder *decoder) { return decoder->channels; }
static uint8_t bits_per_sample(flac_decoder *decoder) { return decoder->bits_per_sample; }
/*-------------------------------------------------
* flac_decoder - constructor
*-------------------------------------------------
*/
void flac_decoder_init(flac_decoder *decoder)
int flac_decoder_init(flac_decoder *decoder)
{
decoder->decoder = FLAC__stream_decoder_new();
decoder->decoder = NULL;
decoder->sample_rate = 0;
decoder->channels = 0;
decoder->bits_per_sample = 0;
@ -43,6 +50,7 @@ void flac_decoder_init(flac_decoder *decoder)
decoder->uncompressed_offset = 0;
decoder->uncompressed_length = 0;
decoder->uncompressed_swap = 0;
return 0;
}
/*-------------------------------------------------
@ -53,10 +61,10 @@ void flac_decoder_init(flac_decoder *decoder)
void flac_decoder_free(flac_decoder* decoder)
{
if ((decoder != NULL) && (decoder->decoder != NULL))
FLAC__stream_decoder_delete(decoder->decoder);
drflac_close(decoder->decoder);
decoder->decoder = NULL;
}
/*-------------------------------------------------
* reset - reset state with the original
* parameters
@ -66,21 +74,13 @@ void flac_decoder_free(flac_decoder* decoder)
static int flac_decoder_internal_reset(flac_decoder* decoder)
{
decoder->compressed_offset = 0;
if (FLAC__stream_decoder_init_stream(decoder->decoder,
&flac_decoder_read_callback_static,
NULL,
&flac_decoder_tell_callback_static,
NULL,
NULL,
&flac_decoder_write_callback_static,
&flac_decoder_metadata_callback_static,
&flac_decoder_error_callback_static, decoder) != FLAC__STREAM_DECODER_INIT_STATUS_OK)
return 0;
return FLAC__stream_decoder_process_until_end_of_metadata(decoder->decoder);
flac_decoder_free(decoder);
decoder->decoder = drflac_open_with_metadata(
flac_decoder_read_callback, flac_decoder_seek_callback,
flac_decoder_metadata_callback, decoder, NULL);
return (decoder->decoder != NULL);
}
/*-------------------------------------------------
* reset - reset state with new memory parameters
* and a custom-generated header
@ -94,43 +94,46 @@ int flac_decoder_reset(flac_decoder* decoder, uint32_t sample_rate, uint8_t num_
{
0x66, 0x4C, 0x61, 0x43, /* +00: 'fLaC' stream header */
0x80, /* +04: metadata block type 0 (STREAMINFO), */
/* flagged as last block */
/* flagged as last block */
0x00, 0x00, 0x22, /* +05: metadata block length = 0x22 */
0x00, 0x00, /* +08: minimum block size */
0x00, 0x00, /* +0A: maximum block size */
0x00, 0x00, 0x00, /* +0C: minimum frame size (0 == unknown) */
0x00, 0x00, 0x00, /* +0F: maximum frame size (0 == unknown) */
0x0A, 0xC4, 0x42, 0xF0, 0x00, 0x00, 0x00, 0x00, /* +12: sample rate (0x0ac44 == 44100), */
/* numchannels (2), sample bits (16), */
/* samples in stream (0 == unknown) */
/* numchannels (2), sample bits (16), */
/* samples in stream (0 == unknown) */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* +1A: MD5 signature (0 == none) */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 /* */
/* +2A: start of stream data */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 /* +2A: start of stream data */
};
memcpy(decoder->custom_header, s_header_template, sizeof(s_header_template));
decoder->custom_header[0x08] = decoder->custom_header[0x0a] = block_size >> 8;
decoder->custom_header[0x09] = decoder->custom_header[0x0b] = block_size & 0xff;
decoder->custom_header[0x08] = decoder->custom_header[0x0a] = (block_size*num_channels) >> 8;
decoder->custom_header[0x09] = decoder->custom_header[0x0b] = (block_size*num_channels) & 0xff;
decoder->custom_header[0x12] = sample_rate >> 12;
decoder->custom_header[0x13] = sample_rate >> 4;
decoder->custom_header[0x14] = (sample_rate << 4) | ((num_channels - 1) << 1);
/* configure the header ahead of the provided buffer */
decoder->compressed_start = (const FLAC__byte *)(decoder->custom_header);
decoder->compressed_start = (const uint8_t *)(decoder->custom_header);
decoder->compressed_length = sizeof(decoder->custom_header);
decoder->compressed2_start = (const FLAC__byte *)(buffer);
decoder->compressed2_start = (const uint8_t *)(buffer);
decoder->compressed2_length = length;
return flac_decoder_internal_reset(decoder);
}
/*-------------------------------------------------
* decode_interleaved - decode to an interleaved
* sound stream
*-------------------------------------------------
*/
#define BUFFER 2352 /* bytes per CD audio sector */
int flac_decoder_decode_interleaved(flac_decoder* decoder, int16_t *samples, uint32_t num_samples, int swap_endian)
{
int16_t buffer[BUFFER];
uint32_t buf_samples;
/* configure the uncompressed buffer */
memset(decoder->uncompressed_start, 0, sizeof(decoder->uncompressed_start));
decoder->uncompressed_start[0] = samples;
@ -138,45 +141,18 @@ int flac_decoder_decode_interleaved(flac_decoder* decoder, int16_t *samples, uin
decoder->uncompressed_length = num_samples;
decoder->uncompressed_swap = swap_endian;
buf_samples = BUFFER / channels(decoder);
/* loop until we get everything we want */
while (decoder->uncompressed_offset < decoder->uncompressed_length)
if (!FLAC__stream_decoder_process_single(decoder->decoder))
while (decoder->uncompressed_offset < decoder->uncompressed_length) {
uint32_t frames = (num_samples < buf_samples ? num_samples : buf_samples);
if (!drflac_read_pcm_frames_s16(decoder->decoder, frames, buffer))
return 0;
flac_decoder_write_callback(decoder, buffer, frames*sizeof(*buffer)*channels(decoder));
num_samples -= frames;
}
return 1;
}
#if 0
/*
*-------------------------------------------------
* decode - decode to an multiple independent
* data streams
*-------------------------------------------------
*/
bool flac_decoder::decode(int16_t **samples, uint32_t num_samples, bool swap_endian)
{
/* make sure we don't have too many channels */
int chans = channels();
if (chans > ARRAY_LENGTH(m_uncompressed_start))
return false;
/* configure the uncompressed buffer */
memset(m_uncompressed_start, 0, sizeof(m_uncompressed_start));
for (int curchan = 0; curchan < chans; curchan++)
m_uncompressed_start[curchan] = samples[curchan];
m_uncompressed_offset = 0;
m_uncompressed_length = num_samples;
m_uncompressed_swap = swap_endian;
/* loop until we get everything we want */
while (m_uncompressed_offset < m_uncompressed_length)
if (!FLAC__stream_decoder_process_single(m_decoder))
return false;
return true;
}
#endif
/*-------------------------------------------------
* finish - finish up the decode
*-------------------------------------------------
@ -185,19 +161,24 @@ bool flac_decoder::decode(int16_t **samples, uint32_t num_samples, bool swap_end
uint32_t flac_decoder_finish(flac_decoder* decoder)
{
/* get the final decoding position and move forward */
FLAC__uint64 position = 0;
FLAC__stream_decoder_get_decode_position(decoder->decoder, &position);
FLAC__stream_decoder_finish(decoder->decoder);
drflac *flac = decoder->decoder;
uint64_t position = decoder->compressed_offset;
/* ugh... there's no function to obtain bytes used in drflac :-/ */
position -= DRFLAC_CACHE_L2_LINES_REMAINING(&flac->bs) * sizeof(drflac_cache_t);
position -= DRFLAC_CACHE_L1_BITS_REMAINING(&flac->bs) / 8;
position -= flac->bs.unalignedByteCount;
/* adjust position if we provided the header */
if (position == 0)
return 0;
if (decoder->compressed_start == (const FLAC__byte *)(decoder->custom_header))
if (decoder->compressed_start == (const uint8_t *)(decoder->custom_header))
position -= decoder->compressed_length;
flac_decoder_free(decoder);
return position;
}
/*-------------------------------------------------
* read_callback - handle reads from the input
* stream
@ -206,128 +187,119 @@ uint32_t flac_decoder_finish(flac_decoder* decoder)
#define MIN(x, y) ((x) < (y) ? (x) : (y))
FLAC__StreamDecoderReadStatus flac_decoder_read_callback_static(const FLAC__StreamDecoder *decoder, FLAC__byte buffer[], size_t *bytes, void *client_data)
static size_t flac_decoder_read_callback(void *userdata, void *buffer, size_t bytes)
{
return flac_decoder_read_callback(client_data, buffer, bytes);
}
FLAC__StreamDecoderReadStatus flac_decoder_read_callback(void* client_data, FLAC__byte buffer[], size_t *bytes)
{
flac_decoder* decoder = (flac_decoder*)client_data;
uint32_t expected = *bytes;
flac_decoder* decoder = (flac_decoder*)userdata;
uint8_t *dst = buffer;
/* copy from primary buffer first */
uint32_t outputpos = 0;
if (outputpos < *bytes && decoder->compressed_offset < decoder->compressed_length)
if (outputpos < bytes && decoder->compressed_offset < decoder->compressed_length)
{
uint32_t bytes_to_copy = MIN(*bytes - outputpos, decoder->compressed_length - decoder->compressed_offset);
memcpy(&buffer[outputpos], decoder->compressed_start + decoder->compressed_offset, bytes_to_copy);
uint32_t bytes_to_copy = MIN(bytes - outputpos, decoder->compressed_length - decoder->compressed_offset);
memcpy(&dst[outputpos], decoder->compressed_start + decoder->compressed_offset, bytes_to_copy);
outputpos += bytes_to_copy;
decoder->compressed_offset += bytes_to_copy;
}
/* once we're out of that, copy from the secondary buffer */
if (outputpos < *bytes && decoder->compressed_offset < decoder->compressed_length + decoder->compressed2_length)
if (outputpos < bytes && decoder->compressed_offset < decoder->compressed_length + decoder->compressed2_length)
{
uint32_t bytes_to_copy = MIN(*bytes - outputpos, decoder->compressed2_length - (decoder->compressed_offset - decoder->compressed_length));
memcpy(&buffer[outputpos], decoder->compressed2_start + decoder->compressed_offset - decoder->compressed_length, bytes_to_copy);
uint32_t bytes_to_copy = MIN(bytes - outputpos, decoder->compressed2_length - (decoder->compressed_offset - decoder->compressed_length));
memcpy(&dst[outputpos], decoder->compressed2_start + decoder->compressed_offset - decoder->compressed_length, bytes_to_copy);
outputpos += bytes_to_copy;
decoder->compressed_offset += bytes_to_copy;
}
*bytes = outputpos;
/* return based on whether we ran out of data */
return (*bytes < expected) ? FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM : FLAC__STREAM_DECODER_READ_STATUS_CONTINUE;
return outputpos;
}
/*-------------------------------------------------
* metadata_callback - handle STREAMINFO metadata
*-------------------------------------------------
*/
void flac_decoder_metadata_callback_static(const FLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data)
static void flac_decoder_metadata_callback(void *userdata, drflac_metadata *metadata)
{
flac_decoder *fldecoder;
flac_decoder *decoder = userdata;
/* ignore all but STREAMINFO metadata */
if (metadata->type != FLAC__METADATA_TYPE_STREAMINFO)
if (metadata->type != DRFLAC_METADATA_BLOCK_TYPE_STREAMINFO)
return;
/* parse out the data we care about */
fldecoder = (flac_decoder *)(client_data);
fldecoder->sample_rate = metadata->data.stream_info.sample_rate;
fldecoder->bits_per_sample = metadata->data.stream_info.bits_per_sample;
fldecoder->channels = metadata->data.stream_info.channels;
decoder->sample_rate = metadata->data.streaminfo.sampleRate;
decoder->bits_per_sample = metadata->data.streaminfo.bitsPerSample;
decoder->channels = metadata->data.streaminfo.channels;
}
/*-------------------------------------------------
* tell_callback - handle requests to find out
* where in the input stream we are
*-------------------------------------------------
*/
FLAC__StreamDecoderTellStatus flac_decoder_tell_callback_static(const FLAC__StreamDecoder *decoder, FLAC__uint64 *absolute_byte_offset, void *client_data)
{
*absolute_byte_offset = ((flac_decoder *)client_data)->compressed_offset;
return FLAC__STREAM_DECODER_TELL_STATUS_OK;
}
/*-------------------------------------------------
* write_callback - handle writes to the output
* stream
*-------------------------------------------------
*/
FLAC__StreamDecoderWriteStatus flac_decoder_write_callback_static(const FLAC__StreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data)
{
return flac_decoder_write_callback(client_data, frame, buffer);
}
FLAC__StreamDecoderWriteStatus flac_decoder_write_callback(void *client_data, const FLAC__Frame *frame, const FLAC__int32 * const buffer[])
static void flac_decoder_write_callback(void *userdata, void *buffer, size_t bytes)
{
int sampnum, chan;
int shift, blocksize;
flac_decoder * decoder = (flac_decoder *)client_data;
assert(frame->header.channels == decoder->channels);
int shift, blocksize;
flac_decoder * decoder = (flac_decoder *)userdata;
int16_t *sampbuf = (int16_t *)buffer;
int sampch = channels(decoder);
uint32_t offset = decoder->uncompressed_offset;
uint16_t usample;
/* interleaved case */
shift = decoder->uncompressed_swap ? 8 : 0;
blocksize = frame->header.blocksize;
blocksize = bytes / (sampch * sizeof(sampbuf[0]));
if (decoder->uncompressed_start[1] == NULL)
{
int16_t *dest = decoder->uncompressed_start[0] + decoder->uncompressed_offset * frame->header.channels;
for (sampnum = 0; sampnum < blocksize && decoder->uncompressed_offset < decoder->uncompressed_length; sampnum++, decoder->uncompressed_offset++)
for (chan = 0; chan < frame->header.channels; chan++)
*dest++ = (int16_t)((((uint16_t)buffer[chan][sampnum]) << shift) | (((uint16_t)buffer[chan][sampnum]) >> shift));
int16_t *dest = decoder->uncompressed_start[0] + offset * sampch;
for (sampnum = 0; sampnum < blocksize && offset < decoder->uncompressed_length; sampnum++, offset++)
for (chan = 0; chan < sampch; chan++) {
usample = (uint16_t)*sampbuf++;
*dest++ = (int16_t)((usample << shift) | (usample >> shift));
}
}
/* non-interleaved case */
else
{
for (sampnum = 0; sampnum < blocksize && decoder->uncompressed_offset < decoder->uncompressed_length; sampnum++, decoder->uncompressed_offset++)
for (chan = 0; chan < frame->header.channels; chan++)
for (sampnum = 0; sampnum < blocksize && offset < decoder->uncompressed_length; sampnum++, offset++)
for (chan = 0; chan < sampch; chan++) {
usample = (uint16_t)*sampbuf++;
if (decoder->uncompressed_start[chan] != NULL)
decoder->uncompressed_start[chan][decoder->uncompressed_offset] = (int16_t) ( (((uint16_t)(buffer[chan][sampnum])) << shift) | ( ((uint16_t)(buffer[chan][sampnum])) >> shift) );
decoder->uncompressed_start[chan][offset] = (int16_t) ((usample << shift) | (usample >> shift));
}
}
return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
decoder->uncompressed_offset = offset;
}
/**
* @fn void flac_decoder::error_callback_static(const FLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data)
*
* @brief -------------------------------------------------
* error_callback - handle errors (ignore them)
* -------------------------------------------------.
*
* @param decoder The decoder.
* @param status The status.
* @param [in,out] client_data If non-null, information describing the client.
/*-------------------------------------------------
* seek_callback - handle seeks on the output
* stream
*-------------------------------------------------
*/
void flac_decoder_error_callback_static(const FLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data)
static drflac_bool32 flac_decoder_seek_callback(void *userdata, int offset, drflac_seek_origin origin)
{
flac_decoder * decoder = (flac_decoder *)userdata;
uint32_t length = decoder->compressed_length + decoder->compressed2_length;
if (origin == drflac_seek_origin_start) {
uint32_t pos = offset;
if (pos <= length) {
decoder->compressed_offset = pos;
return 1;
}
} else if (origin == drflac_seek_origin_current) {
uint32_t pos = decoder->compressed_offset + offset;
if (pos <= length) {
decoder->compressed_offset = pos;
return 1;
}
}
return 0;
}

View File

@ -1,6 +1,6 @@
// license:BSD-3-Clause
// copyright-holders:Aaron Giles
/***************************************************************************
/* license:BSD-3-Clause
* copyright-holders:Aaron Giles
***************************************************************************
flac.h
@ -14,38 +14,37 @@
#define __FLAC_H__
#include <stdint.h>
#include "FLAC/ordinals.h"
#include "FLAC/stream_decoder.h"
//**************************************************************************
// TYPE DEFINITIONS
//**************************************************************************
/***************************************************************************
* TYPE DEFINITIONS
***************************************************************************
*/
typedef struct _flac_decoder flac_decoder;
struct _flac_decoder {
// output state
FLAC__StreamDecoder* decoder; // actual encoder
uint32_t sample_rate; // decoded sample rate
uint8_t channels; // decoded number of channels
uint8_t bits_per_sample; // decoded bits per sample
uint32_t compressed_offset; // current offset in compressed data
const FLAC__byte * compressed_start; // start of compressed data
uint32_t compressed_length; // length of compressed data
const FLAC__byte * compressed2_start; // start of compressed data
uint32_t compressed2_length; // length of compressed data
int16_t * uncompressed_start[8]; // pointer to start of uncompressed data (up to 8 streams)
uint32_t uncompressed_offset; // current position in uncompressed data
uint32_t uncompressed_length; // length of uncompressed data
int uncompressed_swap; // swap uncompressed sample data
uint8_t custom_header[0x2a]; // custom header
/* output state */
void * decoder; /* actual encoder */
uint32_t sample_rate; /* decoded sample rate */
uint8_t channels; /* decoded number of channels */
uint8_t bits_per_sample; /* decoded bits per sample */
uint32_t compressed_offset; /* current offset in compressed data */
const uint8_t * compressed_start; /* start of compressed data */
uint32_t compressed_length; /* length of compressed data */
const uint8_t * compressed2_start; /* start of compressed data */
uint32_t compressed2_length; /* length of compressed data */
int16_t * uncompressed_start[8]; /* pointer to start of uncompressed data (up to 8 streams) */
uint32_t uncompressed_offset; /* current position in uncompressed data */
uint32_t uncompressed_length; /* length of uncompressed data */
int uncompressed_swap; /* swap uncompressed sample data */
uint8_t custom_header[0x2a]; /* custom header */
};
// ======================> flac_decoder
/* ======================> flac_decoder */
void flac_decoder_init(flac_decoder* decoder);
int flac_decoder_init(flac_decoder* decoder);
void flac_decoder_free(flac_decoder* decoder);
int flac_decoder_reset(flac_decoder* decoder, uint32_t sample_rate, uint8_t num_channels, uint32_t block_size, const void *buffer, uint32_t length);
int flac_decoder_decode_interleaved(flac_decoder* decoder, int16_t *samples, uint32_t num_samples, int swap_endian);
uint32_t flac_decoder_finish(flac_decoder* decoder);
#endif // __FLAC_H__
#endif /* __FLAC_H__ */

View File

@ -1,6 +1,6 @@
/* license:BSD-3-Clause
* copyright-holders:Aaron Giles
***************************************************************************
****************************************************************************
huffman.c
@ -112,10 +112,9 @@
#define MAKE_LOOKUP(code,bits) (((code) << 5) | ((bits) & 0x1f))
/***************************************************************************
* IMPLEMENTATION
* **************************************************************************
***************************************************************************
*/
/*-------------------------------------------------
@ -126,7 +125,8 @@
struct huffman_decoder* create_huffman_decoder(int numcodes, int maxbits)
{
struct huffman_decoder* decoder;
struct huffman_decoder* decoder = NULL;
/* limit to 24 bits */
if (maxbits > 24)
return NULL;
@ -181,10 +181,10 @@ uint32_t huffman_decode_one(struct huffman_decoder* decoder, struct bitstream* b
enum huffman_error huffman_import_tree_rle(struct huffman_decoder* decoder, struct bitstream* bitbuf)
{
enum huffman_error error;
int numbits, curnode;
enum huffman_error error;
/* bits per entry depends on the maxbits */
int numbits;
int curnode;
if (decoder->maxbits >= 16)
numbits = 5;
else if (decoder->maxbits >= 8)
@ -243,19 +243,18 @@ enum huffman_error huffman_import_tree_rle(struct huffman_decoder* decoder, stru
enum huffman_error huffman_import_tree_huffman(struct huffman_decoder* decoder, struct bitstream* bitbuf)
{
int start;
int last = 0;
int count = 0;
int index;
int curcode;
uint32_t temp;
enum huffman_error error;
uint8_t rlefullbits = 0;
int index, count = 0;
int start;
uint32_t temp;
enum huffman_error error;
/* start by parsing the lengths for the small tree */
struct huffman_decoder* smallhuff = create_huffman_decoder(24, 6);
smallhuff->huffnode[0].numbits = bitstream_read(bitbuf, 3);
start = bitstream_read(bitbuf, 3) + 1;
for (index = 1; index < 24; index++)
{
if (index < start || count == 7)
@ -310,7 +309,6 @@ enum huffman_error huffman_import_tree_huffman(struct huffman_decoder* decoder,
return bitstream_overflow(bitbuf) ? HUFFERR_INPUT_BUFFER_TOO_SMALL : HUFFERR_NONE;
}
/*-------------------------------------------------
* compute_tree_from_histo - common backend for
* computing a tree based on the data histogram
@ -319,15 +317,16 @@ enum huffman_error huffman_import_tree_huffman(struct huffman_decoder* decoder,
enum huffman_error huffman_compute_tree_from_histo(struct huffman_decoder* decoder)
{
/* compute the number of data items in the histogram */
int i;
uint32_t upperweight;
uint32_t lowerweight = 0;
uint32_t lowerweight;
uint32_t upperweight;
/* compute the number of data items in the histogram */
uint32_t sdatacount = 0;
for (i = 0; i < decoder->numcodes; i++)
sdatacount += decoder->datahisto[i];
/* binary search to achieve the optimum encoding */
lowerweight = 0;
upperweight = sdatacount * 2;
while (1)
{
@ -352,8 +351,6 @@ enum huffman_error huffman_compute_tree_from_histo(struct huffman_decoder* decod
return huffman_assign_canonical_codes(decoder);
}
/***************************************************************************
* INTERNAL FUNCTIONS
***************************************************************************
@ -376,7 +373,6 @@ static int huffman_tree_node_compare(const void *item1, const void *item2)
return (int)node1->bits - (int)node2->bits;
}
/*-------------------------------------------------
* build_tree - build a huffman tree based on the
* data distribution
@ -385,11 +381,12 @@ static int huffman_tree_node_compare(const void *item1, const void *item2)
int huffman_build_tree(struct huffman_decoder* decoder, uint32_t totaldata, uint32_t totalweight)
{
int nextalloc;
int curcode;
int nextalloc;
int listitems = 0;
int maxbits = 0;
/* make a list of all non-zero nodes */
struct node_t** list = (struct node_t**)malloc(sizeof(struct node_t*) * decoder->numcodes * 2);
int curcode, listitems = 0;
memset(decoder->huffnode, 0, decoder->numcodes * sizeof(decoder->huffnode[0]));
for (curcode = 0; curcode < decoder->numcodes; curcode++)
if (decoder->datahisto[curcode] != 0)
@ -403,24 +400,27 @@ int huffman_build_tree(struct huffman_decoder* decoder, uint32_t totaldata, uint
if (decoder->huffnode[curcode].weight == 0)
decoder->huffnode[curcode].weight = 1;
}
/*
#if 0
fprintf(stderr, "Pre-sort:\n");
for (int i = 0; i < listitems; i++) {
fprintf(stderr, "weight: %d code: %d\n", list[i]->m_weight, list[i]->m_bits);
}
*/
#endif
/* sort the list by weight, largest weight first */
qsort(&list[0], listitems, sizeof(list[0]), huffman_tree_node_compare);
/*
#if 0
fprintf(stderr, "Post-sort:\n");
for (int i = 0; i < listitems; i++) {
fprintf(stderr, "weight: %d code: %d\n", list[i]->m_weight, list[i]->m_bits);
}
fprintf(stderr, "===================\n");
*/
#endif
/* now build the tree */
nextalloc = decoder->numcodes;
while (listitems > 1)
{
int curitem;
@ -453,7 +453,7 @@ int huffman_build_tree(struct huffman_decoder* decoder, uint32_t totaldata, uint
node->numbits = 0;
node->bits = 0;
// if we have a non-zero weight, compute the number of bits
/* if we have a non-zero weight, compute the number of bits */
if (node->weight > 0)
{
/* determine the number of bits for this node */
@ -469,7 +469,6 @@ int huffman_build_tree(struct huffman_decoder* decoder, uint32_t totaldata, uint
return maxbits;
}
/*-------------------------------------------------
* assign_canonical_codes - assign canonical codes
* to all the nodes based on the number of bits
@ -479,9 +478,9 @@ int huffman_build_tree(struct huffman_decoder* decoder, uint32_t totaldata, uint
enum huffman_error huffman_assign_canonical_codes(struct huffman_decoder* decoder)
{
int curcode, codelen;
uint32_t curstart = 0;
/* build up a histogram of bit lengths */
int curcode, codelen;
uint32_t bithisto[33] = { 0 };
for (curcode = 0; curcode < decoder->numcodes; curcode++)
{
@ -512,7 +511,6 @@ enum huffman_error huffman_assign_canonical_codes(struct huffman_decoder* decode
return HUFFERR_NONE;
}
/*-------------------------------------------------
* build_lookup_table - build a lookup table for
* fast decoding
@ -521,8 +519,8 @@ enum huffman_error huffman_assign_canonical_codes(struct huffman_decoder* decode
void huffman_build_lookup_table(struct huffman_decoder* decoder)
{
/* iterate over all codes */
int curcode;
/* iterate over all codes */
for (curcode = 0; curcode < decoder->numcodes; curcode++)
{
/* process all nodes which have non-zero bits */

View File

@ -1,6 +1,6 @@
// license:BSD-3-Clause
// copyright-holders:Aaron Giles
/***************************************************************************
/* license:BSD-3-Clause
* copyright-holders:Aaron Giles
***************************************************************************
huffman.h
@ -16,9 +16,10 @@
#include "bitstream.h"
//**************************************************************************
// CONSTANTS
//**************************************************************************
/***************************************************************************
* CONSTANTS
***************************************************************************
*/
enum huffman_error
{
@ -31,49 +32,50 @@ enum huffman_error
HUFFERR_TOO_MANY_CONTEXTS
};
//**************************************************************************
// TYPE DEFINITIONS
//**************************************************************************
/***************************************************************************
* TYPE DEFINITIONS
***************************************************************************
*/
typedef uint16_t lookup_value;
// a node in the huffman tree
/* a node in the huffman tree */
struct node_t
{
struct node_t* parent; // pointer to parent node
uint32_t count; // number of hits on this node
uint32_t weight; // assigned weight of this node
uint32_t bits; // bits used to encode the node
uint8_t numbits; // number of bits needed for this node
struct node_t* parent; /* pointer to parent node */
uint32_t count; /* number of hits on this node */
uint32_t weight; /* assigned weight of this node */
uint32_t bits; /* bits used to encode the node */
uint8_t numbits; /* number of bits needed for this node */
};
// ======================> huffman_context_base
/* ======================> huffman_context_base */
// context class for decoding
/* context class for decoding */
struct huffman_decoder
{
// internal state
uint32_t numcodes; // number of total codes being processed
uint8_t maxbits; // maximum bits per code
uint8_t prevdata; // value of the previous data (for delta-RLE encoding)
int rleremaining; // number of RLE bytes remaining (for delta-RLE encoding)
lookup_value * lookup; // pointer to the lookup table
struct node_t * huffnode; // array of nodes
uint32_t * datahisto; // histogram of data values
/* internal state */
uint32_t numcodes; /* number of total codes being processed */
uint8_t maxbits; /* maximum bits per code */
uint8_t prevdata; /* value of the previous data (for delta-RLE encoding) */
int rleremaining; /* number of RLE bytes remaining (for delta-RLE encoding) */
lookup_value * lookup; /* pointer to the lookup table */
struct node_t * huffnode; /* array of nodes */
uint32_t * datahisto; /* histogram of data values */
// array versions of the info we need
//node_t* huffnode_array; //[_NumCodes];
//lookup_value* lookup_array; //[1 << _MaxBits];
/* array versions of the info we need */
#if 0
node_t* huffnode_array; /* [_NumCodes]; */
lookup_value* lookup_array; /* [1 << _MaxBits]; */
#endif
};
// ======================> huffman_decoder
/* ======================> huffman_decoder */
struct huffman_decoder* create_huffman_decoder(int numcodes, int maxbits);
void delete_huffman_decoder(struct huffman_decoder* decoder);
// single item operations
/* single item operations */
uint32_t huffman_decode_one(struct huffman_decoder* decoder, struct bitstream* bitbuf);
enum huffman_error huffman_import_tree_rle(struct huffman_decoder* decoder, struct bitstream* bitbuf);

View File

@ -480,4 +480,4 @@ void input_end_frame(unsigned int cycles)
}
}
}
}
}

View File

@ -292,7 +292,7 @@ void m68k_run(unsigned int cycles)
#ifdef HOOK_CPU
/* Trigger execution hook */
if (cpu_hook)
if (UNLIKELY(cpu_hook))
cpu_hook(HOOK_M68K_E, 0, REG_PC, 0);
#endif

View File

@ -859,7 +859,7 @@ INLINE uint m68ki_read_8(uint address)
else val = READ_BYTE(temp->base, (address) & 0xffff);
#ifdef HOOK_CPU
if (cpu_hook)
if (UNLIKELY(cpu_hook))
cpu_hook(HOOK_M68K_R, 1, address, val);
#endif
@ -879,7 +879,7 @@ INLINE uint m68ki_read_16(uint address)
else val = *(uint16 *)(temp->base + ((address) & 0xffff));
#ifdef HOOK_CPU
if (cpu_hook)
if (UNLIKELY(cpu_hook))
cpu_hook(HOOK_M68K_R, 2, address, val);
#endif
@ -899,7 +899,7 @@ INLINE uint m68ki_read_32(uint address)
else val = m68k_read_immediate_32(address);
#ifdef HOOK_CPU
if (cpu_hook)
if (UNLIKELY(cpu_hook))
cpu_hook(HOOK_M68K_R, 4, address, val);
#endif
@ -913,7 +913,7 @@ INLINE void m68ki_write_8(uint address, uint value)
m68ki_set_fc(FLAG_S | FUNCTION_CODE_USER_DATA) /* auto-disable (see m68kcpu.h) */
#ifdef HOOK_CPU
if (cpu_hook)
if (UNLIKELY(cpu_hook))
cpu_hook(HOOK_M68K_W, 1, address, value);
#endif
@ -930,7 +930,7 @@ INLINE void m68ki_write_16(uint address, uint value)
m68ki_check_address_error(address, MODE_WRITE, FLAG_S | FUNCTION_CODE_USER_DATA); /* auto-disable (see m68kcpu.h) */
#ifdef HOOK_CPU
if (cpu_hook)
if (UNLIKELY(cpu_hook))
cpu_hook(HOOK_M68K_W, 2, address, value);
#endif
@ -947,7 +947,7 @@ INLINE void m68ki_write_32(uint address, uint value)
m68ki_check_address_error(address, MODE_WRITE, FLAG_S | FUNCTION_CODE_USER_DATA) /* auto-disable (see m68kcpu.h) */
#ifdef HOOK_CPU
if (cpu_hook)
if (UNLIKELY(cpu_hook))
cpu_hook(HOOK_M68K_W, 4, address, value);
#endif

View File

@ -53,6 +53,15 @@
#define ALIGNED_(x) __attribute__ ((aligned(x)))
#endif
/* Provide the compiler with branch prediction information */
#if defined(__GNUC__)
#define LIKELY(x) __builtin_expect(!!(x), 1)
#define UNLIKELY(x) __builtin_expect(!!(x), 0)
#else
#define LIKELY(x) x
#define UNLIKELY(x) x
#endif
/* Default CD image file access (read-only) functions */
/* If you need to override default stdio.h functions with custom filesystem API,
redefine following macros in platform specific include file (osd.h) or Makefile

View File

@ -108,8 +108,13 @@ static void z80_request_68k_bus_access(void)
}
}
/* average Z80 wait-states when accessing 68k area */
Z80.cycles += 3 * 15;
/* approximate 68k wait-states during Z80 access to 68k bus (cf https://docs.google.com/document/d/1ST9GbFfPnIjLT5loytFCm3pB0kWQ1Oe34DCBBV8saY8) */
/* value is adjusted to get ride of graphical glitches in Rick Dangerous 2 title screen when bus refresh delays are also emulated and still get */
/* "M68K DELAY ON Z80 ROM READ" test "passed" in Ti_'s test ROM (misc_test.bin), although the measured delay value is still slightly too high. */
m68k.cycles += ((Z80.cycles % 7) + 68);
/* average Z80 wait-states when accessing 68k bus (cf https://docs.google.com/document/d/1ST9GbFfPnIjLT5loytFCm3pB0kWQ1Oe34DCBBV8saY8) */
Z80.cycles += (3 * 15);
}
unsigned char z80_memory_r(unsigned int address)

View File

@ -86,7 +86,7 @@ struct blip_t
#define BLIP_BUFFER_STATE_BUFFER_SIZE 16
typedef struct blip_buffer_state_t
struct blip_buffer_state_t
{
fixed_t offset;
#ifdef BLIP_MONO

View File

@ -741,7 +741,6 @@ void vdp_dma_update(unsigned int cycles)
if (!dma_length)
{
/* DMA source address registers are incremented during DMA (even DMA Fill) */
if (config.vdp_fix_dma_boundary_bug) {
/*
* NOTICE: VDP has a hardware bug where DMA transfer source address is not incremented properly,
@ -2218,7 +2217,7 @@ static void vdp_bus_w(unsigned int data)
}
#ifdef HOOK_CPU
if (cpu_hook)
if (UNLIKELY(cpu_hook))
cpu_hook(HOOK_VRAM_W, 2, addr, data);
#endif
@ -2267,7 +2266,7 @@ static void vdp_bus_w(unsigned int data)
}
#ifdef HOOK_CPU
if (cpu_hook)
if (UNLIKELY(cpu_hook))
cpu_hook(HOOK_CRAM_W, 2, addr, data);
#endif
@ -2293,7 +2292,7 @@ static void vdp_bus_w(unsigned int data)
}
#ifdef HOOK_CPU
if (cpu_hook)
if (UNLIKELY(cpu_hook))
cpu_hook(HOOK_VSRAM_W, 2, addr, data);
#endif
@ -2504,7 +2503,7 @@ static unsigned int vdp_68k_data_r_m5(void)
data = *(uint16 *)&vram[addr & 0xFFFE];
#ifdef HOOK_CPU
if (cpu_hook)
if (UNLIKELY(cpu_hook))
cpu_hook(HOOK_VRAM_R, 2, addr, data);
#endif
@ -2533,7 +2532,7 @@ static unsigned int vdp_68k_data_r_m5(void)
data |= (fifo[fifo_idx] & ~0x7FF);
#ifdef HOOK_CPU
if (cpu_hook)
if (UNLIKELY(cpu_hook))
cpu_hook(HOOK_VSRAM_R, 2, addr, data);
#endif
@ -2555,7 +2554,7 @@ static unsigned int vdp_68k_data_r_m5(void)
data |= (fifo[fifo_idx] & ~0xEEE);
#ifdef HOOK_CPU
if (cpu_hook)
if (UNLIKELY(cpu_hook))
cpu_hook(HOOK_CRAM_R, 2, addr, data);
#endif
@ -2574,7 +2573,7 @@ static unsigned int vdp_68k_data_r_m5(void)
data |= (fifo[fifo_idx] & ~0xFF);
#ifdef HOOK_CPU
if (cpu_hook)
if (UNLIKELY(cpu_hook))
cpu_hook(HOOK_VRAM_R, 2, addr, data);
#endif
@ -3051,7 +3050,6 @@ static void vdp_dma_68k_ext(unsigned int length)
source += 2;
if (!config.vdp_fix_dma_boundary_bug) {
source = (reg[23] << 17) | (source & 0x1FFFF);
/* 128k DMA window */
source = (reg[23] << 17) | (source & 0x1FFFF);
}

View File

@ -1042,6 +1042,7 @@ void color_update_m4(int index, unsigned int data)
case SYSTEM_SG:
case SYSTEM_SGII:
case SYSTEM_SGII_RAM_EXT:
{
/* Fixed TMS99xx palette */
if (index & 0x0F)
@ -1540,7 +1541,6 @@ void render_bg_m5(int line)
pf_row_mask = playfield_row_mask;
pf_shift = playfield_shift;
/* Window & Plane A */
a = (reg[18] & 0x1F) << 3;
w = (reg[18] >> 7) & 1;
@ -1668,7 +1668,7 @@ void render_bg_m5(int line)
/* Plane A line buffer */
dst = (uint32 *)&linebuf[1][0x20 + (start << 4)];
start_real = start + (config.h40_extra_columns / 4);
end_real = end - (config.h40_extra_columns / 4);
@ -1767,7 +1767,7 @@ void render_bg_m5_vs(int line)
for(column = 0; column < end; column++, index++)
{
int column_capped = column - (config.h40_extra_columns / 4);
int column_capped = column - (config.h40_extra_columns / 4);
column_capped = MAX(0, MIN(column_capped, 19));
/* Plane B vertical scroll */
#ifdef LSB_FIRST
@ -1885,7 +1885,7 @@ void render_bg_m5_vs(int line)
/* Plane A line buffer */
dst = (uint32 *)&linebuf[1][0x20 + (start << 4)];
start_real = start + (config.h40_extra_columns / 4);
end_real = end - (config.h40_extra_columns / 4);
@ -1905,9 +1905,9 @@ void render_bg_m5_vs(int line)
}
/* Enhanced function that allows each cell to be vscrolled individually, instead of being limited to 2-cell */
void render_bg_m5_vs_enhanced(int line)
void render_bg_m5_vs_enhanced(int line)
{
int column;
int column, v_offset;
int start_real, end_real;
uint32 atex, atbuf, *src, *dst;
uint32 v_line, next_v_line, *nt;
@ -1915,10 +1915,6 @@ void render_bg_m5_vs_enhanced(int line)
uint32 *vs;
int a, w, start = 0, end;
uint32 shift, index;
/* Vertical scroll offset */
int v_offset = 0;
/* Common data */
uint32 xscroll = *(uint32 *)&vram[hscb + ((line & hscroll_mask) << 2)];
if (
@ -1989,7 +1985,7 @@ void render_bg_m5_vs_enhanced(int line)
for(column = 0; column < end; column++, index++)
{
int column_capped = column - (config.h40_extra_columns / 4);
int column_capped = column - (config.h40_extra_columns / 4);
column_capped = MAX(0, MIN(column_capped, 19));
/* Plane B vertical scroll */
#ifdef LSB_FIRST
@ -2167,9 +2163,9 @@ void render_bg_m5_vs_enhanced(int line)
#endif
#ifdef LSB_FIRST
v_line = (line + v_offset + vs[column_capped]) & pf_row_mask;
v_line = (line + v_offset + vs[column]) & pf_row_mask;
#else
v_line = (line + v_offset + (vs[column_capped] >> 16)) & pf_row_mask;
v_line = (line + v_offset + (vs[column] >> 16)) & pf_row_mask;
#endif
nt = (uint32 *)&vram[ntab + (((v_line >> 3) << pf_shift) & 0x1FC0)];
@ -2208,7 +2204,7 @@ void render_bg_m5_vs_enhanced(int line)
/* Plane A line buffer */
dst = (uint32 *)&linebuf[1][0x20 + (start << 4)];
start_real = start + (config.h40_extra_columns / 4);
end_real = end - (config.h40_extra_columns / 4);
@ -2383,7 +2379,7 @@ void render_bg_m5_im2(int line)
/* Plane A line buffer */
dst = (uint32 *)&linebuf[1][0x20 + (start << 4)];
start_real = start + (config.h40_extra_columns / 4);
end_real = end - (config.h40_extra_columns / 4);
@ -2564,7 +2560,7 @@ void render_bg_m5_im2_vs(int line)
for(column = start; column < end; column++, index++)
{
int column_capped = column - (config.h40_extra_columns / 4);
int column_capped = column - (config.h40_extra_columns / 4);
column_capped = MAX(0, MIN(column_capped, 19));
/* Plane A vertical scroll */
#ifdef LSB_FIRST
@ -2599,7 +2595,7 @@ void render_bg_m5_im2_vs(int line)
/* Plane A line buffer */
dst = (uint32 *)&linebuf[1][0x20 + (start << 4)];
start_real = start + (config.h40_extra_columns / 4);
end_real = end - (config.h40_extra_columns / 4);
@ -2744,7 +2740,7 @@ void render_bg_m5(int line)
/* Pattern row index */
v_line = (line & 7) << 3;
int start_real = start + (config.h40_extra_columns / 4);
int end_real = end - (config.h40_extra_columns / 4);
@ -2944,8 +2940,8 @@ void render_bg_m5_vs(int line)
/* Pattern row index */
v_line = (line & 7) << 3;
int start_real = start + (config.h40_extra_columns / 4);
int start_real = start + (config.h40_extra_columns / 4);
int end_real = end - (config.h40_extra_columns / 4);
for(column = start; column < end; column++)
@ -2991,7 +2987,7 @@ void render_bg_m5_vs(int line)
for(column = 0; column < width; column++, index++)
{
int column_capped = column - (config.h40_extra_columns / 4);
int column_capped = column - (config.h40_extra_columns / 4);
column_capped = MAX(0, MIN(column_capped, 19));
/* Plane B vertical scroll */
#ifdef LSB_FIRST
@ -3212,7 +3208,7 @@ void render_bg_m5_vs_enhanced(int line)
/* Pattern row index */
v_line = (line & 7) << 3;
int start_real = start + (config.h40_extra_columns / 4);
int end_real = end - (config.h40_extra_columns / 4);
@ -3259,7 +3255,7 @@ void render_bg_m5_vs_enhanced(int line)
for(column = 0; column < width; column++, index++)
{
int column_capped = column - (config.h40_extra_columns / 4);
int column_capped = column - (config.h40_extra_columns / 4);
column_capped = MAX(0, MIN(column_capped, 19));
/* Plane B vertical scroll */
#ifdef LSB_FIRST
@ -3502,7 +3498,7 @@ void render_bg_m5_im2(int line)
/* Pattern row index */
v_line = ((line & 7) << 1 | odd) << 3;
int start_real = start + (config.h40_extra_columns / 4);
int end_real = end - (config.h40_extra_columns / 4);
@ -3704,7 +3700,7 @@ void render_bg_m5_im2_vs(int line)
/* Pattern row index */
v_line = ((line & 7) << 1 | odd) << 3;
int start_real = start + (config.h40_extra_columns / 4);
int end_real = end - (config.h40_extra_columns / 4);
@ -4732,7 +4728,7 @@ void parse_satb_m5(int line)
/* Update sprite list (only name, attribute & xpos are parsed from VRAM) */
object_info->attr = p[link + 2];
if (config.h40_extra_columns > 0)
object_info->xpos = p[link + 3];
else
@ -5019,7 +5015,7 @@ void render_line(int line)
/* Left-most column blanking */
if (reg[0] & 0x20)
{
if (system_hw > SYSTEM_SGII)
if (system_hw >= SYSTEM_MARKIII)
{
memset(&linebuf[0][0x20], 0x40, 8);
}

View File

@ -2528,7 +2528,7 @@ static chd_error zlib_codec_init(void *codec, uint32_t hunkbytes)
/* handle an error */
if (err != CHDERR_NONE)
free(data);
zlib_codec_free(data);
return err;
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -138,6 +138,7 @@ typedef struct
uint8 enhanced_vscroll;
uint8 enhanced_vscroll_limit;
uint8 cd_latency;
bool cd_precache;
#ifdef USE_PER_SOUND_CHANNELS_CONFIG
unsigned int psg_ch_volumes[4];
int32 md_ch_volumes[6];
@ -163,6 +164,7 @@ extern char MS_BIOS_JP[256];
extern void osd_input_update(void);
extern int load_archive(char *filename, unsigned char *buffer, int maxsize, char *extension);
extern void ROMCheatUpdate(void);
extern retro_log_printf_t log_cb;
#ifndef cdStream
#define cdStream RFILE

View File

@ -41,6 +41,14 @@ ifneq ($(OS),Windows_NT)
DEFINES += -DHAVE_ALLOCA_H
endif
ifneq ($(findstring Darwin,$(shell uname -a)),)
platform = osx
endif
ifeq ($(platform), osx)
CFLAGS += -Winvalid-utf8 -Wstrict-prototypes
endif
SRCDIR = ../core
INCLUDES = -I$(SRCDIR) -I$(SRCDIR)/z80 -I$(SRCDIR)/m68k -I$(SRCDIR)/sound -I$(SRCDIR)/input_hw -I$(SRCDIR)/cart_hw -I$(SRCDIR)/cart_hw/svp -I$(SRCDIR)/cd_hw -I$(SRCDIR)/ntsc -I$(SRCDIR)/tremor -I$(SRCDIR)/../sdl -I$(SRCDIR)/../sdl/sdl2
LIBS = `sdl2-config --libs` -lz -lm

View File

@ -2,7 +2,7 @@
#ifndef _CONFIG_H_
#define _CONFIG_H_
#include "shared.h"
#include "types.h"
/****************************************************************************
* Config Option