mirror of
https://github.com/libretro/Genesis-Plus-GX-Wide.git
synced 2024-11-23 00:09:44 +00:00
Sync with non-wide
This commit is contained in:
parent
5474f11328
commit
7d56f9f304
1
.gitignore
vendored
1
.gitignore
vendored
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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++)
|
||||
|
@ -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/)
|
||||
|
206
core/cd_hw/cdd.c
206
core/cd_hw/cdd.c
@ -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;
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -1,6 +1,6 @@
|
||||
/* license:BSD-3-Clause
|
||||
* copyright-holders:Aaron Giles
|
||||
***************************************************************************
|
||||
***************************************************************************
|
||||
|
||||
bitstream.h
|
||||
|
||||
|
@ -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, §or[ECC_P_OFFSET + byte], §or[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, §or[ECC_Q_OFFSET + byte], §or[ECC_Q_OFFSET + ECC_Q_NUM_BYTES + byte]);
|
||||
}
|
||||
|
||||
|
@ -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
@ -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
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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__ */
|
||||
|
@ -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 */
|
||||
|
@ -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);
|
||||
|
@ -480,4 +480,4 @@ void input_end_frame(unsigned int cycles)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
7953
libretro/libretro.c
7953
libretro/libretro.c
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
@ -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
|
||||
|
@ -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
|
||||
|
@ -2,7 +2,7 @@
|
||||
#ifndef _CONFIG_H_
|
||||
#define _CONFIG_H_
|
||||
|
||||
#include "shared.h"
|
||||
#include "types.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Config Option
|
||||
|
Loading…
Reference in New Issue
Block a user