Do changes to reduce diff against upstream GPGX
This commit is contained in:
parent
821d632fc7
commit
ef72cbff43
|
@ -1 +1 @@
|
|||
Subproject commit 499dd30a13c400b154e22bfc50522b2a309afbc2
|
||||
Subproject commit ca03348aadbe1951eca04d2d7b65fbcf0d8d30c1
|
|
@ -23,6 +23,7 @@ CCFLAGS := -Iutil \
|
|||
-DUSE_32BPP_RENDERING \
|
||||
-DHOOK_CPU \
|
||||
-DINLINE=static\ __inline__ \
|
||||
-DcdStream=cdStream \
|
||||
-fcommon
|
||||
|
||||
LDFLAGS :=
|
||||
|
@ -80,7 +81,7 @@ SRCS = $(GPGX_DIR)/core/sound/sound.c \
|
|||
$(GPGX_DIR)/core/cart_hw/megasd.c \
|
||||
$(GPGX_DIR)/core/debug/cpuhook.c \
|
||||
$(GPGX_DIR)/core/loadrom.c \
|
||||
cinterface/cddImpl.c \
|
||||
cinterface/cdStreamImpl.c \
|
||||
cinterface/cinterface.c \
|
||||
util/scrc32.c
|
||||
|
||||
|
|
|
@ -12,7 +12,7 @@ extern ECL_ENTRY void (*biz_readcb)(unsigned addr);
|
|||
extern ECL_ENTRY void (*biz_writecb)(unsigned addr);
|
||||
extern CDCallback biz_cdcb;
|
||||
|
||||
extern ECL_ENTRY void (*cdd_readcallback)(int lba, void *dest, int audio);
|
||||
extern ECL_ENTRY void (*cdd_readcallback)(int lba, void *dest, int subcode);
|
||||
|
||||
enum eCDLog_AddrType
|
||||
{
|
||||
|
|
|
@ -0,0 +1,202 @@
|
|||
#include <emulibc.h>
|
||||
#include <shared.h>
|
||||
|
||||
#include "callbacks.h"
|
||||
|
||||
#define SECTOR_DATA_SIZE 2352
|
||||
#define SECTOR_SUBCODE_SIZE 96
|
||||
|
||||
ECL_INVISIBLE toc_t hotswap_toc;
|
||||
int8 cd_index = 0;
|
||||
|
||||
struct cdStream_t
|
||||
{
|
||||
int sector_size;
|
||||
int num_sectors;
|
||||
int64_t current_sector;
|
||||
int64_t current_offset;
|
||||
int64_t end_offset;
|
||||
uint8_t* cache_buffer;
|
||||
uint8_t* sectors_cached;
|
||||
};
|
||||
|
||||
static cdStream cd_streams[128];
|
||||
static cdStream subcode_streams[128];
|
||||
ECL_INVISIBLE static int cache_is_allocated[256];
|
||||
|
||||
#define ALLOC_CACHE(stream) do \
|
||||
{ \
|
||||
if (UNLIKELY(!cache_is_allocated[(uint8)cd_index + stream->sector_size == SECTOR_SUBCODE_SIZE ? 128 : 0])) \
|
||||
{ \
|
||||
stream->cache_buffer = alloc_invisible(stream->end_offset); \
|
||||
stream->sectors_cached = alloc_invisible(stream->num_sectors); \
|
||||
memset(stream->sectors_cached, 0, stream->num_sectors); \
|
||||
cache_is_allocated[(uint8)cd_index + stream->sector_size == SECTOR_SUBCODE_SIZE ? 128 : 0] = 1; \
|
||||
} \
|
||||
} while (0);
|
||||
|
||||
static void cdStreamInit(cdStream* stream, int is_subcode)
|
||||
{
|
||||
stream->sector_size = is_subcode ? SECTOR_SUBCODE_SIZE : SECTOR_DATA_SIZE;
|
||||
stream->num_sectors = cdd.toc.end; // should only be called with current CD
|
||||
stream->current_sector = 0;
|
||||
stream->current_offset = 0;
|
||||
stream->end_offset = stream->sector_size * (int64_t)stream->num_sectors;
|
||||
ALLOC_CACHE(stream);
|
||||
}
|
||||
|
||||
cdStream* cdStreamOpen(const char* fname)
|
||||
{
|
||||
// This shouldn't happen
|
||||
if (cd_index < 0)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char* fext = strrchr(fname, '.');
|
||||
if (!fext)
|
||||
{
|
||||
if (!strcmp(fname, "PRIMARY_CD"))
|
||||
{
|
||||
if (load_archive("PRIMARY_CD", (unsigned char*)&cdd.toc, sizeof(toc_t), NULL))
|
||||
{
|
||||
cd_index = 0;
|
||||
cdStreamInit(&cd_streams[0], 0);
|
||||
return &cd_streams[0];
|
||||
}
|
||||
}
|
||||
else if (!strcmp(fname, "HOTSWAP_CD"))
|
||||
{
|
||||
memcpy(&cdd.toc, &hotswap_toc, sizeof(toc_t));
|
||||
cdStreamInit(&cd_streams[cd_index], 0);
|
||||
return &cd_streams[cd_index];
|
||||
}
|
||||
}
|
||||
else if (!strcmp(fext, ".iso"))
|
||||
{
|
||||
// an .iso will attempt to be loaded for the "secondary" CD
|
||||
if (load_archive("SECONDARY_CD", (unsigned char*)&cdd.toc, sizeof(toc_t), NULL))
|
||||
{
|
||||
cd_index = 0;
|
||||
cdStreamInit(&cd_streams[0], 0);
|
||||
return &cd_streams[0];
|
||||
}
|
||||
}
|
||||
else if (!strcmp(fext, ".sub"))
|
||||
{
|
||||
// separate stream for subcode
|
||||
cdStreamInit(&subcode_streams[cd_index], 1);
|
||||
return &subcode_streams[cd_index];
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void cdStreamClose(cdStream* stream)
|
||||
{
|
||||
// nothing to do
|
||||
}
|
||||
|
||||
static uint8_t* cdStreamGetSector(cdStream* restrict stream, unsigned* offset)
|
||||
{
|
||||
if (stream->current_sector >= stream->num_sectors)
|
||||
{
|
||||
static uint8_t empty_sector[SECTOR_DATA_SIZE];
|
||||
*offset = 0;
|
||||
return empty_sector;
|
||||
}
|
||||
|
||||
*offset = stream->current_offset - (stream->current_sector * stream->sector_size);
|
||||
uint8_t* sector_cache = &stream->cache_buffer[stream->current_offset - *offset];
|
||||
|
||||
if (!stream->sectors_cached[stream->current_sector])
|
||||
{
|
||||
cdd_readcallback(stream->current_sector, sector_cache, stream->sector_size == SECTOR_SUBCODE_SIZE);
|
||||
stream->sectors_cached[stream->current_sector] = 1;
|
||||
}
|
||||
|
||||
return sector_cache;
|
||||
}
|
||||
|
||||
size_t cdStreamRead(void* restrict buffer, size_t size, size_t count, cdStream* restrict stream)
|
||||
{
|
||||
ALLOC_CACHE(stream);
|
||||
|
||||
size_t bytes_to_read = size * count; // in practice, this shouldn't ever overflow
|
||||
|
||||
// we'll 0 fill the bytes past EOF, although we'll still report the bytes actually read
|
||||
size_t ret = bytes_to_read;
|
||||
if (stream->current_offset + ret > stream->end_offset)
|
||||
{
|
||||
ret = stream->end_offset - stream->current_offset;
|
||||
}
|
||||
|
||||
while (bytes_to_read > 0)
|
||||
{
|
||||
unsigned offset;
|
||||
uint8_t* sector = cdStreamGetSector(stream, &offset);
|
||||
|
||||
unsigned bytes_to_copy = stream->sector_size - offset;
|
||||
if (bytes_to_copy > bytes_to_read)
|
||||
{
|
||||
bytes_to_copy = bytes_to_read;
|
||||
}
|
||||
|
||||
memcpy(buffer, sector + offset, bytes_to_copy);
|
||||
bytes_to_read -= bytes_to_copy;
|
||||
|
||||
stream->current_offset += bytes_to_copy;
|
||||
if (bytes_to_copy + offset >= stream->sector_size)
|
||||
{
|
||||
stream->current_sector++;
|
||||
}
|
||||
|
||||
if (UNLIKELY(stream->current_offset >= stream->end_offset))
|
||||
{
|
||||
stream->current_offset = stream->end_offset;
|
||||
stream->current_sector = stream->num_sectors;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int cdStreamSeek(cdStream* stream, int64_t offset, int origin)
|
||||
{
|
||||
switch (origin)
|
||||
{
|
||||
case SEEK_SET:
|
||||
stream->current_offset = offset;
|
||||
break;
|
||||
case SEEK_CUR:
|
||||
stream->current_offset += offset;
|
||||
break;
|
||||
case SEEK_END:
|
||||
stream->current_offset = stream->end_offset + offset;
|
||||
break;
|
||||
}
|
||||
|
||||
if (stream->current_offset < 0)
|
||||
{
|
||||
stream->current_offset = 0;
|
||||
}
|
||||
|
||||
if (stream->current_offset > stream->end_offset)
|
||||
{
|
||||
stream->current_offset = stream->end_offset;
|
||||
}
|
||||
|
||||
stream->current_sector = stream->current_offset / stream->sector_size;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int64_t cdStreamTell(cdStream* stream)
|
||||
{
|
||||
return stream->current_offset;
|
||||
}
|
||||
|
||||
char* cdStreamGets(char* restrict str, int count, cdStream* restrict stream)
|
||||
{
|
||||
// This is only used for GPGX's .cue file parsing, which is not used in our case
|
||||
return NULL;
|
||||
}
|
|
@ -1,524 +0,0 @@
|
|||
#include "shared.h"
|
||||
#include "megasd.h"
|
||||
#include <callbacks.h>
|
||||
|
||||
static int sampleLba = 0;
|
||||
static int sampleOffset = 0;
|
||||
static int tocLba = 0;
|
||||
|
||||
void cdd_reset(void)
|
||||
{
|
||||
/* reset drive access latency */
|
||||
cdd.latency = 0;
|
||||
|
||||
/* reset track index */
|
||||
cdd.index = 0;
|
||||
|
||||
/* reset logical block address */
|
||||
cdd.lba = 0;
|
||||
|
||||
/* reset logical block address for audio*/
|
||||
sampleLba = 0;
|
||||
sampleOffset = 0;
|
||||
|
||||
/* reset logical block address for Toc*/
|
||||
tocLba = 0;
|
||||
|
||||
/* reset status */
|
||||
cdd.status = cdd.loaded ? CD_TOC : NO_DISC;
|
||||
|
||||
/* reset CD-DA fader (full volume) */
|
||||
cdd.fader[0] = cdd.fader[1] = 0x400;
|
||||
|
||||
/* clear CD-DA output */
|
||||
cdd.audio[0] = cdd.audio[1] = 0;
|
||||
}
|
||||
|
||||
typedef struct
|
||||
{
|
||||
toc_t toc;
|
||||
} frontendcd_t;
|
||||
|
||||
int cdd_load(const char *key, char *header)
|
||||
{
|
||||
frontendcd_t fecd;
|
||||
char data[2048];
|
||||
int startoffs;
|
||||
|
||||
int bytes = sizeof(frontendcd_t);
|
||||
if (load_archive(key, (unsigned char *)&fecd, bytes, NULL) != bytes)
|
||||
return 0;
|
||||
|
||||
// look for valid header
|
||||
cdd_readcallback(0, data, 0);
|
||||
if (memcmp("SEGADISCSYSTEM", data, 14) == 0)
|
||||
startoffs = 0;
|
||||
else if (memcmp("SEGADISCSYSTEM", data + 16, 14) == 0)
|
||||
startoffs = 16;
|
||||
else
|
||||
return 0;
|
||||
// copy security block
|
||||
memcpy(header, data + startoffs, 0x210);
|
||||
|
||||
// copy disk information
|
||||
memcpy(&cdd.toc, &fecd.toc, sizeof(toc_t));
|
||||
|
||||
/* Valid CD-ROM Mode 1 track found ? */
|
||||
if (cdd.toc.tracks[0].type == TYPE_MODE1)
|
||||
{
|
||||
/* simulate audio tracks if none found */
|
||||
if (cdd.toc.last == 1)
|
||||
{
|
||||
/* some games require exact TOC infos */
|
||||
if (strstr(header + 0x180,"T-95035") != NULL)
|
||||
{
|
||||
/* Snatcher */
|
||||
cdd.toc.last = cdd.toc.end = 0;
|
||||
do
|
||||
{
|
||||
cdd.toc.tracks[cdd.toc.last].start = cdd.toc.end;
|
||||
cdd.toc.tracks[cdd.toc.last].end = cdd.toc.tracks[cdd.toc.last].start + toc_snatcher[cdd.toc.last];
|
||||
cdd.toc.end = cdd.toc.tracks[cdd.toc.last].end;
|
||||
cdd.toc.last++;
|
||||
}
|
||||
while (cdd.toc.last < 21);
|
||||
}
|
||||
else if (strstr(header + 0x180,"T-127015") != NULL)
|
||||
{
|
||||
/* Lunar - The Silver Star */
|
||||
cdd.toc.last = cdd.toc.end = 0;
|
||||
do
|
||||
{
|
||||
cdd.toc.tracks[cdd.toc.last].start = cdd.toc.end;
|
||||
cdd.toc.tracks[cdd.toc.last].end = cdd.toc.tracks[cdd.toc.last].start + toc_lunar[cdd.toc.last];
|
||||
cdd.toc.end = cdd.toc.tracks[cdd.toc.last].end;
|
||||
cdd.toc.last++;
|
||||
}
|
||||
while (cdd.toc.last < 52);
|
||||
}
|
||||
else if (strstr(header + 0x180,"T-113045") != NULL)
|
||||
{
|
||||
/* Shadow of the Beast II */
|
||||
cdd.toc.last = cdd.toc.end = 0;
|
||||
do
|
||||
{
|
||||
cdd.toc.tracks[cdd.toc.last].start = cdd.toc.end;
|
||||
cdd.toc.tracks[cdd.toc.last].end = cdd.toc.tracks[cdd.toc.last].start + toc_shadow[cdd.toc.last];
|
||||
cdd.toc.end = cdd.toc.tracks[cdd.toc.last].end;
|
||||
cdd.toc.last++;
|
||||
}
|
||||
while (cdd.toc.last < 15);
|
||||
}
|
||||
else if (strstr(header + 0x180,"T-143025") != NULL)
|
||||
{
|
||||
/* Dungeon Explorer */
|
||||
cdd.toc.last = cdd.toc.end = 0;
|
||||
do
|
||||
{
|
||||
cdd.toc.tracks[cdd.toc.last].start = cdd.toc.end;
|
||||
cdd.toc.tracks[cdd.toc.last].end = cdd.toc.tracks[cdd.toc.last].start + toc_dungeon[cdd.toc.last];
|
||||
cdd.toc.end = cdd.toc.tracks[cdd.toc.last].end;
|
||||
cdd.toc.last++;
|
||||
}
|
||||
while (cdd.toc.last < 13);
|
||||
}
|
||||
else if (strstr(header + 0x180,"MK-4410") != NULL)
|
||||
{
|
||||
/* Final Fight CD (USA, Europe) */
|
||||
cdd.toc.last = cdd.toc.end = 0;
|
||||
do
|
||||
{
|
||||
cdd.toc.tracks[cdd.toc.last].start = cdd.toc.end;
|
||||
cdd.toc.tracks[cdd.toc.last].end = cdd.toc.tracks[cdd.toc.last].start + toc_ffight[cdd.toc.last];
|
||||
cdd.toc.end = cdd.toc.tracks[cdd.toc.last].end;
|
||||
cdd.toc.last++;
|
||||
}
|
||||
while (cdd.toc.last < 26);
|
||||
}
|
||||
else if (strstr(header + 0x180,"G-6013") != NULL)
|
||||
{
|
||||
/* Final Fight CD (Japan) */
|
||||
cdd.toc.last = cdd.toc.end = 0;
|
||||
do
|
||||
{
|
||||
cdd.toc.tracks[cdd.toc.last].start = cdd.toc.end;
|
||||
cdd.toc.tracks[cdd.toc.last].end = cdd.toc.tracks[cdd.toc.last].start + toc_ffightj[cdd.toc.last];
|
||||
cdd.toc.end = cdd.toc.tracks[cdd.toc.last].end;
|
||||
cdd.toc.last++;
|
||||
}
|
||||
while (cdd.toc.last < 29);
|
||||
}
|
||||
else if (strstr(header + 0x180,"T-06201-01") != NULL)
|
||||
{
|
||||
/* Sewer Shark (USA) (REV1) */
|
||||
/* no audio track */
|
||||
}
|
||||
else
|
||||
{
|
||||
/* default TOC (99 tracks & 2s per audio tracks) */
|
||||
do
|
||||
{
|
||||
cdd.toc.tracks[cdd.toc.last].start = cdd.toc.end + 2*75;
|
||||
cdd.toc.tracks[cdd.toc.last].end = cdd.toc.tracks[cdd.toc.last].start + 2*75;
|
||||
cdd.toc.end = cdd.toc.tracks[cdd.toc.last].end;
|
||||
cdd.toc.last++;
|
||||
}
|
||||
while ((cdd.toc.last < 99) && (cdd.toc.end < 56*60*75));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cdd.loaded = 1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
void cdd_unload(void)
|
||||
{
|
||||
cdd.loaded = 0;
|
||||
cdd_readcallback = NULL;
|
||||
|
||||
/* reset TOC */
|
||||
memset(&cdd.toc, 0x00, sizeof(cdd.toc));
|
||||
}
|
||||
|
||||
void cdd_update(void)
|
||||
{
|
||||
#ifdef LOG_CDD
|
||||
error("LBA = %d (track n<>%d)(latency=%d)\n", cdd.lba, cdd.index, cdd.latency);
|
||||
#endif
|
||||
|
||||
/* seeking disc */
|
||||
if (cdd.status == CD_SEEK)
|
||||
{
|
||||
/* drive latency */
|
||||
if (cdd.latency > 0)
|
||||
{
|
||||
cdd.latency--;
|
||||
return;
|
||||
}
|
||||
|
||||
/* drive is ready */
|
||||
cdd.status = CD_PAUSE;
|
||||
}
|
||||
|
||||
/* reading disc */
|
||||
else if (cdd.status == CD_PLAY)
|
||||
{
|
||||
/* drive latency */
|
||||
if (cdd.latency > 0)
|
||||
{
|
||||
cdd.latency--;
|
||||
return;
|
||||
}
|
||||
|
||||
/* track type */
|
||||
if (!cdd.index)
|
||||
{
|
||||
/* DATA sector header (CD-ROM Mode 1) */
|
||||
uint8 header[4];
|
||||
uint32 msf = cdd.lba + 150;
|
||||
header[0] = lut_BCD_8[(msf / 75) / 60];
|
||||
header[1] = lut_BCD_8[(msf / 75) % 60];
|
||||
header[2] = lut_BCD_8[(msf % 75)];
|
||||
header[3] = 0x01;
|
||||
|
||||
/* data track sector read is controlled by CDC */
|
||||
cdc_decoder_update(*(uint32 *)(header));
|
||||
cdd.lba++;
|
||||
}
|
||||
else if (cdd.index < cdd.toc.last)
|
||||
{
|
||||
/* check against audio track start index */
|
||||
if (cdd.lba >= cdd.toc.tracks[cdd.index].start)
|
||||
{
|
||||
/* audio track playing */
|
||||
// if it wasn't before, set the audio start position
|
||||
if (scd.regs[0x36>>1].byte.h)
|
||||
{
|
||||
sampleLba = cdd.lba + 1;
|
||||
sampleOffset = 0;
|
||||
}
|
||||
scd.regs[0x36>>1].byte.h = 0x00;
|
||||
}
|
||||
|
||||
/* audio blocks are still sent to CDC as well as CD DAC/Fader */
|
||||
cdc_decoder_update(0);
|
||||
|
||||
/* next audio block is automatically read */
|
||||
cdd.lba++;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* end of disc */
|
||||
cdd.status = CD_END;
|
||||
return;
|
||||
}
|
||||
|
||||
/* check end of current track */
|
||||
if (cdd.lba >= cdd.toc.tracks[cdd.index].end)
|
||||
{
|
||||
/* play next track */
|
||||
cdd.index++;
|
||||
|
||||
/* PAUSE between tracks */
|
||||
scd.regs[0x36>>1].byte.h = 0x01;
|
||||
}
|
||||
}
|
||||
|
||||
/* scanning disc */
|
||||
else if (cdd.status == CD_SCAN)
|
||||
{
|
||||
/* fast-forward or fast-rewind */
|
||||
cdd.lba += cdd.scanOffset;
|
||||
sampleLba += cdd.scanOffset;
|
||||
|
||||
/* check current track limits */
|
||||
if (cdd.lba >= cdd.toc.tracks[cdd.index].end)
|
||||
{
|
||||
/* next track */
|
||||
cdd.index++;
|
||||
|
||||
/* skip directly to track start position */
|
||||
cdd.lba = cdd.toc.tracks[cdd.index].start;
|
||||
|
||||
/* AUDIO track playing ? */
|
||||
if (cdd.status == CD_PLAY)
|
||||
{
|
||||
scd.regs[0x36>>1].byte.h = 0x00;
|
||||
// set audio start point
|
||||
sampleLba = cdd.lba;
|
||||
sampleOffset = 0;
|
||||
}
|
||||
}
|
||||
else if (cdd.lba < cdd.toc.tracks[cdd.index].start)
|
||||
{
|
||||
/* previous track */
|
||||
cdd.index--;
|
||||
|
||||
/* skip directly to track end position */
|
||||
cdd.lba = cdd.toc.tracks[cdd.index].end;
|
||||
}
|
||||
|
||||
/* check disc limits */
|
||||
if (cdd.index < 0)
|
||||
{
|
||||
cdd.index = 0;
|
||||
cdd.lba = 0;
|
||||
}
|
||||
else if (cdd.index >= cdd.toc.last)
|
||||
{
|
||||
/* no AUDIO track playing */
|
||||
scd.regs[0x36>>1].byte.h = 0x01;
|
||||
|
||||
/* end of disc */
|
||||
cdd.index = cdd.toc.last;
|
||||
cdd.lba = cdd.toc.end;
|
||||
cdd.status = CD_END;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void cdd_read_data(uint8 *dst, uint8 *subheader)
|
||||
{
|
||||
/* only allow reading (first) CD-ROM track sectors */
|
||||
if (cdd.toc.tracks[cdd.index].type && (cdd.lba >= 0))
|
||||
{
|
||||
/* check sector size */
|
||||
if (cdd.sectorSize == 2048)
|
||||
{
|
||||
/* read Mode 1 user data (2048 bytes) */
|
||||
cdd_readcallback(cdd.lba, dst, 0);
|
||||
// cdStreamSeek(trackStream[0], cdd.lba * 2048, SEEK_SET);
|
||||
// cdStreamRead(dst, 2048, 1, trackStream[0]);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* check if sub-header is required (Mode 2 sector only) */
|
||||
if (!subheader)
|
||||
{
|
||||
/* skip block sync pattern (12 bytes) + block header (4 bytes) then read Mode 1 user data (2048 bytes) */
|
||||
cdd_readcallback(cdd.lba, dst, 0);
|
||||
// cdStreamSeek(trackStream[0], (cdd.lba * 2352) + 12 + 4, SEEK_SET);
|
||||
// cdStreamRead(dst, 2048, 1, trackStream[0]);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* skip block sync pattern (12 bytes) + block header (4 bytes) + Mode 2 sub-header (first 4 bytes) then read Mode 2 sub-header (last 4 bytes) */
|
||||
|
||||
|
||||
uint8_t buffer[2352];
|
||||
cdd_readcallback(cdd.lba, buffer, 0);
|
||||
|
||||
// cdStreamSeek(trackStream[0], (cdd.lba * 2352) + 12 + 4 + 4, SEEK_SET);
|
||||
size_t pos = 12 + 4 + 4;
|
||||
|
||||
// cdStreamRead(subheader, 4, 1, trackStream[0]);
|
||||
memcpy(subheader, &buffer[pos], 4); pos += 4;
|
||||
|
||||
/* read Mode 2 user data (max 2328 bytes) */
|
||||
// cdStreamRead(dst, 2328, 1, trackStream[0]);
|
||||
memcpy(dst, &buffer[pos], 2328);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void cdd_seek_audio(int index, int lba)
|
||||
{
|
||||
cdd.index = index;
|
||||
sampleLba = lba;
|
||||
// /* seek to track position */
|
||||
// if (trackStream[index])
|
||||
// {
|
||||
// /* PCM AUDIO track */
|
||||
// cdStreamSeek(trackStream[index], (lba * 2352) - trackOffset[index], SEEK_SET);
|
||||
// }
|
||||
}
|
||||
|
||||
void cdd_read_audio(unsigned int samples)
|
||||
{
|
||||
/* previous audio outputs */
|
||||
int prev_l = cdd.audio[0];
|
||||
int prev_r = cdd.audio[1];
|
||||
|
||||
/* audio track playing ? */
|
||||
if (!scd.regs[0x36>>1].byte.h)
|
||||
{
|
||||
int i, mul, l, r;
|
||||
|
||||
/* current CD-DA fader volume */
|
||||
int curVol = cdd.fader[0];
|
||||
|
||||
/* CD-DA fader volume setup (0-1024) */
|
||||
int endVol = cdd.fader[1];
|
||||
|
||||
/* read samples from current block */
|
||||
{
|
||||
#ifdef LSB_FIRST
|
||||
int16 *ptr = (int16 *) (cdc.ram);
|
||||
#else
|
||||
uint8 *ptr = cdc.ram;
|
||||
#endif
|
||||
{
|
||||
char scratch[2352];
|
||||
// copy the end of current sector
|
||||
int nsampreq = samples;
|
||||
unsigned char *dest = cdc.ram;
|
||||
cdd_readcallback(sampleLba, scratch, 1);
|
||||
memcpy(cdc.ram, scratch + sampleOffset * 4, 2352 - sampleOffset * 4);
|
||||
sampleLba++;
|
||||
nsampreq -= 588 - sampleOffset;
|
||||
dest += 2352 - sampleOffset * 4;
|
||||
sampleOffset = 0;
|
||||
// fill full sectors
|
||||
while (nsampreq >= 588)
|
||||
{
|
||||
cdd_readcallback(sampleLba, scratch, 1);
|
||||
memcpy(dest, scratch, 2352);
|
||||
sampleLba++;
|
||||
nsampreq -= 588;
|
||||
dest += 2352;
|
||||
}
|
||||
// do last partial sector
|
||||
if (nsampreq > 0)
|
||||
{
|
||||
cdd_readcallback(sampleLba, scratch, 1);
|
||||
memcpy(dest, scratch, nsampreq * 4);
|
||||
sampleOffset = nsampreq;
|
||||
dest += nsampreq * 4;
|
||||
nsampreq = 0;
|
||||
}
|
||||
//printf("samples: %i\n", samples);
|
||||
//memset(cdc.ram, 0, samples * 4);
|
||||
//fread(cdc.ram, 1, samples * 4, cdd.toc.tracks[cdd.index].fd);
|
||||
}
|
||||
|
||||
/* process 16-bit (little-endian) stereo samples */
|
||||
for (i=0; i<samples; i++)
|
||||
{
|
||||
/* CD-DA fader multiplier (cf. LC7883 datasheet) */
|
||||
/* (MIN) 0,1,2,3,4,8,12,16,20...,1020,1024 (MAX) */
|
||||
mul = (curVol & 0x7fc) ? (curVol & 0x7fc) : (curVol & 0x03);
|
||||
|
||||
/* left & right channels */
|
||||
#ifdef LSB_FIRST
|
||||
l = ((ptr[0] * mul) / 1024);
|
||||
r = ((ptr[1] * mul) / 1024);
|
||||
ptr+=2;
|
||||
#else
|
||||
l = (((int16)((ptr[0] + ptr[1]*256)) * mul) / 1024);
|
||||
r = (((int16)((ptr[2] + ptr[3]*256)) * mul) / 1024);
|
||||
ptr+=4;
|
||||
#endif
|
||||
|
||||
/* CD-DA output mixing volume (0-100%) */
|
||||
l = (l * config.cdda_volume) / 100;
|
||||
r = (r * config.cdda_volume) / 100;
|
||||
|
||||
/* update blip buffer */
|
||||
blip_add_delta_fast(snd.blips[2], i, l-prev_l, r-prev_r);
|
||||
prev_l = l;
|
||||
prev_r = r;
|
||||
|
||||
/* update CD-DA fader volume (one step/sample) */
|
||||
if (curVol < endVol)
|
||||
{
|
||||
/* fade-in */
|
||||
curVol++;
|
||||
}
|
||||
else if (curVol > endVol)
|
||||
{
|
||||
/* fade-out */
|
||||
curVol--;
|
||||
}
|
||||
else if (!curVol)
|
||||
{
|
||||
/* audio will remain muted until next setup */
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* save current CD-DA fader volume */
|
||||
cdd.fader[0] = curVol;
|
||||
|
||||
/* save last audio output for next frame */
|
||||
cdd.audio[0] = prev_l;
|
||||
cdd.audio[1] = prev_r;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* no audio output */
|
||||
if (prev_l | prev_r)
|
||||
{
|
||||
/* update blip buffer */
|
||||
blip_add_delta_fast(snd.blips[2], 0, -prev_l, -prev_r);
|
||||
|
||||
/* save audio output for next frame */
|
||||
cdd.audio[0] = 0;
|
||||
cdd.audio[1] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* end of blip buffer timeframe */
|
||||
blip_end_frame(snd.blips[2], samples);
|
||||
}
|
||||
|
||||
void cdd_seek_toc(int lba)
|
||||
{
|
||||
tocLba = lba;
|
||||
// if (tocStream == NULL) return;
|
||||
// cdStreamSeek(tocStream, cdd.lba * 96, SEEK_SET);
|
||||
}
|
||||
|
||||
void cdd_read_toc(uint8 *dst, size_t size)
|
||||
{
|
||||
if (size > 2352) { fprintf(stderr, "Excessive size requested (%lu) on cdd_read_toc()\n", size); exit(1); }
|
||||
uint8_t buffer[2352];
|
||||
cdd_readcallback(tocLba, buffer, 0);
|
||||
memcpy(dst, buffer, size);
|
||||
// if (tocStream == NULL) return;
|
||||
// cdStreamRead(dst, 1, size, tocStream);
|
||||
}
|
|
@ -4,10 +4,6 @@
|
|||
#include <emulibc.h>
|
||||
#include "callbacks.h"
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#define snprintf _snprintf
|
||||
#endif
|
||||
|
||||
#include <shared.h>
|
||||
#include <genesis.h>
|
||||
#include <md_ntsc.h>
|
||||
|
@ -35,6 +31,8 @@ char romextension[4];
|
|||
static int16 soundbuffer[4096];
|
||||
static int nsamples;
|
||||
|
||||
int cinterface_force_sram;
|
||||
|
||||
int cinterface_render_bga = 1;
|
||||
int cinterface_render_bgb = 1;
|
||||
int cinterface_render_bgw = 1;
|
||||
|
@ -60,7 +58,7 @@ ECL_ENTRY void (*biz_execcb)(unsigned addr);
|
|||
ECL_ENTRY void (*biz_readcb)(unsigned addr);
|
||||
ECL_ENTRY void (*biz_writecb)(unsigned addr);
|
||||
CDCallback biz_cdcb = NULL;
|
||||
ECL_ENTRY void (*cdd_readcallback)(int lba, void *dest, int audio);
|
||||
ECL_ENTRY void (*cdd_readcallback)(int lba, void *dest, int subcode);
|
||||
uint8 *tempsram;
|
||||
|
||||
static void update_viewport(void)
|
||||
|
@ -138,7 +136,7 @@ GPGX_EX void gpgx_set_input_callback(ECL_ENTRY void (*fecb)(void))
|
|||
input_callback_cb = fecb;
|
||||
}
|
||||
|
||||
GPGX_EX void gpgx_set_cdd_callback(ECL_ENTRY void (*cddcb)(int lba, void *dest, int audio))
|
||||
GPGX_EX void gpgx_set_cdd_callback(ECL_ENTRY void (*cddcb)(int lba, void *dest, int subcode))
|
||||
{
|
||||
cdd_readcallback = cddcb;
|
||||
}
|
||||
|
@ -190,11 +188,27 @@ GPGX_EX void gpgx_advance(void)
|
|||
nsamples = audio_update(soundbuffer);
|
||||
}
|
||||
|
||||
GPGX_EX void gpgx_swap_disc(const toc_t* toc)
|
||||
extern toc_t hotswap_toc;
|
||||
extern int8 cd_index;
|
||||
|
||||
GPGX_EX void gpgx_swap_disc(const toc_t* toc, int8 index)
|
||||
{
|
||||
if (system_hw == SYSTEM_MCD)
|
||||
{
|
||||
cdd_hotswap(toc);
|
||||
if (toc)
|
||||
{
|
||||
char header[0x210];
|
||||
cd_index = index;
|
||||
memcpy(&hotswap_toc, toc, sizeof(toc_t));
|
||||
cdd_load("HOTSWAP_CD", header);
|
||||
}
|
||||
else
|
||||
{
|
||||
cd_index = -1;
|
||||
cdd_unload();
|
||||
}
|
||||
|
||||
cdd_reset();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -216,7 +230,7 @@ typedef struct
|
|||
} vdpview_t;
|
||||
|
||||
|
||||
extern uint8 ALIGNED_(4) bg_pattern_cache[0x80000];
|
||||
extern uint8 bg_pattern_cache[0x80000];
|
||||
uint32_t pixel[0x100];
|
||||
|
||||
GPGX_EX void gpgx_get_vdp_view(vdpview_t *view)
|
||||
|
@ -235,10 +249,36 @@ GPGX_EX void gpgx_get_vdp_view(vdpview_t *view)
|
|||
view->ntw.baseaddr = ntwb;
|
||||
}
|
||||
|
||||
extern int eeprom_i2c_get_size(void);
|
||||
|
||||
// internal: computes sram size (no brams)
|
||||
int saveramsize(void)
|
||||
static int saveramsize(void)
|
||||
{
|
||||
return sram_get_actual_size();
|
||||
// the variables in SRAM_T are all part of "configuration", so we don't have to save those.
|
||||
// the only thing that needs to be saved is the SRAM itself and the SEEPROM struct (if applicable)
|
||||
|
||||
if (!sram.on)
|
||||
return 0;
|
||||
switch (sram.custom)
|
||||
{
|
||||
case 0: // plain bus access saveram
|
||||
break;
|
||||
case 1: // i2c
|
||||
return eeprom_i2c_get_size();
|
||||
case 2: // spi
|
||||
return sizeof(sram.sram); // it doesn't appear to mask anything internally
|
||||
case 3: // 93c
|
||||
return 128; // limited to 128 bytes (note: SMS only)
|
||||
default:
|
||||
return sizeof(sram.sram); // ???
|
||||
}
|
||||
// figure size for plain bus access saverams
|
||||
{
|
||||
int startaddr = sram.start / 8192;
|
||||
int endaddr = sram.end / 8192 + 1;
|
||||
int size = (endaddr - startaddr) * 8192;
|
||||
return size;
|
||||
}
|
||||
}
|
||||
|
||||
GPGX_EX void gpgx_clear_sram(void)
|
||||
|
@ -345,17 +385,70 @@ GPGX_EX int gpgx_put_sram(const uint8 *data, int size)
|
|||
|
||||
GPGX_EX void gpgx_poke_cram(int addr, uint8 val)
|
||||
{
|
||||
write_cram_byte(addr, val);
|
||||
uint16 *p;
|
||||
uint16 data;
|
||||
int index;
|
||||
|
||||
p = (uint16 *)&cram[addr & 0x7E];
|
||||
data = *p;
|
||||
data = ((data & 0x1C0) << 3) | ((data & 0x038) << 2) | ((data & 0x007) << 1);
|
||||
|
||||
if (addr & 1)
|
||||
{
|
||||
data &= 0xFF00;
|
||||
data |= val;
|
||||
}
|
||||
else
|
||||
{
|
||||
data &= 0x00FF;
|
||||
data |= val << 8;
|
||||
}
|
||||
|
||||
data = ((data & 0xE00) >> 3) | ((data & 0x0E0) >> 2) | ((data & 0x00E) >> 1);
|
||||
|
||||
if (*p != data)
|
||||
{
|
||||
index = (addr >> 1) & 0x3F;
|
||||
*p = data;
|
||||
|
||||
if (index & 0x0F)
|
||||
{
|
||||
color_update_m5(index, data);
|
||||
}
|
||||
|
||||
if (index == border)
|
||||
{
|
||||
color_update_m5(0x00, data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
GPGX_EX void gpgx_poke_vram(int addr, uint8 val)
|
||||
{
|
||||
write_vram_byte(addr, val);
|
||||
uint8 *p;
|
||||
addr &= 0xFFFF;
|
||||
p = &vram[addr];
|
||||
if (*p != val)
|
||||
{
|
||||
int name;
|
||||
*p = val;
|
||||
// copy of MARK_BG_DIRTY(addr) (to avoid putting this code in vdp_ctrl.c)
|
||||
name = (addr >> 5) & 0x7FF;
|
||||
if (bg_name_dirty[name] == 0)
|
||||
{
|
||||
bg_name_list[bg_list_index++] = name;
|
||||
}
|
||||
bg_name_dirty[name] |= (1 << ((addr >> 2) & 7));
|
||||
}
|
||||
}
|
||||
|
||||
GPGX_EX void gpgx_flush_vram(void)
|
||||
{
|
||||
flush_vram_cache();
|
||||
if (bg_list_index)
|
||||
{
|
||||
update_bg_pattern_cache(bg_list_index);
|
||||
bg_list_index = 0;
|
||||
}
|
||||
}
|
||||
|
||||
GPGX_EX const char* gpgx_get_memdom(int which, void **area, int *size)
|
||||
|
@ -615,9 +708,9 @@ GPGX_EX int gpgx_init(const char* feromextension,
|
|||
ECL_ENTRY int (*feload_archive_cb)(const char *filename, unsigned char *buffer, int maxsize),
|
||||
struct InitSettings *settings)
|
||||
{
|
||||
_debug_puts("Initializing GPGX native...");
|
||||
fprintf(stderr, "Initializing GPGX native...\n");
|
||||
|
||||
force_sram = settings->ForceSram;
|
||||
cinterface_force_sram = settings->ForceSram;
|
||||
|
||||
memset(&bitmap, 0, sizeof(bitmap));
|
||||
|
||||
|
@ -632,10 +725,6 @@ GPGX_EX int gpgx_init(const char* feromextension,
|
|||
bitmap.data = alloc_plain(2 * 1024 * 1024);
|
||||
tempsram = alloc_plain(24 * 1024);
|
||||
|
||||
// cd_hw/cd_cart.h
|
||||
|
||||
ext.cd_hw.cartridge.area = alloc_plain(SCD_CARTRIDGE_AREA_SIZE);
|
||||
|
||||
// Initializing ram deepfreeze list
|
||||
#ifdef USE_RAM_DEEPFREEZE
|
||||
deepfreeze_list_size = 0;
|
||||
|
@ -749,8 +838,15 @@ GPGX_EX int gpgx_init(const char* feromextension,
|
|||
config.input[i].padtype = settings->SixButton ? DEVICE_PAD6B : DEVICE_PAD3B;
|
||||
}
|
||||
|
||||
if (!load_rom("PRIMARY_ROM", "PRIMARY_CD", "SECONDARY_CD"))
|
||||
return 0;
|
||||
// first try to load our main CD
|
||||
if (!load_rom("PRIMARY_CD"))
|
||||
{
|
||||
// otherwise, try to load our ROM
|
||||
if (!load_rom("PRIMARY_ROM"))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
audio_init(44100, 0);
|
||||
system_init();
|
||||
|
@ -827,7 +923,12 @@ GPGX_EX void gpgx_set_sprite_limit_enabled(int enabled)
|
|||
|
||||
GPGX_EX void gpgx_invalidate_pattern_cache(void)
|
||||
{
|
||||
vdp_invalidate_full_cache();
|
||||
bg_list_index = (reg[1] & 0x04) ? 0x800 : 0x200;
|
||||
for (int i = 0; i < bg_list_index; i++)
|
||||
{
|
||||
bg_name_list[i] = i;
|
||||
bg_name_dirty[i] = 0xFF;
|
||||
}
|
||||
}
|
||||
|
||||
typedef struct
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
#ifndef CD_STREAM_H
|
||||
#define CD_STREAM_H
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
|
||||
struct cdStream_t;
|
||||
typedef struct cdStream_t cdStream;
|
||||
|
||||
extern cdStream *cdStreamOpen(const char *fname);
|
||||
extern void cdStreamClose(cdStream *stream);
|
||||
extern size_t cdStreamRead(void *restrict buffer, size_t size, size_t count, cdStream *restrict stream);
|
||||
extern int cdStreamSeek(cdStream *stream, int64_t offset, int origin);
|
||||
extern int64_t cdStreamTell(cdStream *stream);
|
||||
extern char *cdStreamGets(char *restrict str, int count, cdStream *restrict stream);
|
||||
|
||||
#endif
|
|
@ -1,15 +1,12 @@
|
|||
#pragma once
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#include <stdio.h>
|
||||
typedef unsigned char bool;
|
||||
#define strncasecmp _strnicmp
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "scrc32.h"
|
||||
#include "cdStream.h"
|
||||
|
||||
#define MAX_INPUTS 8
|
||||
#define MAX_KEYS 8
|
||||
#define MAXPATHLEN 1024
|
||||
|
@ -93,7 +90,5 @@ extern char MS_BIOS_US[256];
|
|||
extern char MS_BIOS_EU[256];
|
||||
extern char MS_BIOS_JP[256];
|
||||
|
||||
void osd_input_update(void);
|
||||
int load_archive(const char *filename, unsigned char *buffer, int maxsize, char *extension);
|
||||
void real_input_callback(void);
|
||||
|
||||
extern void osd_input_update(void);
|
||||
extern int load_archive(const char *filename, unsigned char *buffer, int maxsize, char *extension);
|
||||
|
|
Loading…
Reference in New Issue