Do changes to reduce diff against upstream GPGX

This commit is contained in:
CasualPokePlayer 2024-04-26 11:57:38 -07:00
parent 821d632fc7
commit ef72cbff43
8 changed files with 352 additions and 560 deletions

@ -1 +1 @@
Subproject commit 499dd30a13c400b154e22bfc50522b2a309afbc2
Subproject commit ca03348aadbe1951eca04d2d7b65fbcf0d8d30c1

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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