mirror of
https://github.com/holub/mame
synced 2025-05-11 00:28:49 +03:00
Fixed crash bug in DCS games.
Updated the fcompress APIs to allow for specifying a compression level. Removed the concept of state saving tags, which was a hack to get save states to work with multiple CPU cores. Simplified the state saving system as a result, performing the operation in a single pass and without allocating a full blob of memory. Also enabled minimal compression.
This commit is contained in:
parent
4ee312ca39
commit
e26c70d35b
@ -262,11 +262,9 @@ void cpuexec_init(running_machine *machine)
|
||||
classdata->timedint_timer = timer_alloc(machine, trigger_periodic_interrupt, device);
|
||||
|
||||
/* initialize this CPU */
|
||||
state_save_push_tag(cpunum + 1);
|
||||
num_regs = state_save_get_reg_count(machine);
|
||||
cpu_init(device, cpunum, classdata->clock, standard_irq_callback);
|
||||
num_regs = state_save_get_reg_count(machine) - num_regs;
|
||||
state_save_pop_tag();
|
||||
|
||||
/* fetch post-initialization data */
|
||||
classdata->icount = cpu_get_icount_ptr(device);
|
||||
|
@ -386,12 +386,13 @@ void mame_fclose(mame_file *file)
|
||||
|
||||
/*-------------------------------------------------
|
||||
mame_fcompress - enable/disable streaming file
|
||||
compression via zlib
|
||||
compression via zlib; level is 0 to disable
|
||||
compression, or up to 9 for max compression
|
||||
-------------------------------------------------*/
|
||||
|
||||
file_error mame_fcompress(mame_file *file, int compress)
|
||||
file_error mame_fcompress(mame_file *file, int level)
|
||||
{
|
||||
return core_fcompress(file->file, compress);
|
||||
return core_fcompress(file->file, level);
|
||||
}
|
||||
|
||||
|
||||
|
@ -98,7 +98,7 @@ file_error mame_fopen_ram(const void *data, UINT32 length, UINT32 openflags, mam
|
||||
/* close an open file */
|
||||
void mame_fclose(mame_file *file);
|
||||
|
||||
/* enable/disable streaming file compression via zlib */
|
||||
/* enable/disable streaming file compression via zlib; level is 0 to disable compression, or up to 9 for max compression */
|
||||
file_error mame_fcompress(mame_file *file, int compress);
|
||||
|
||||
|
||||
|
@ -3974,7 +3974,7 @@ static time_t playback_init(running_machine *machine)
|
||||
fatalerror("Input file is for " GAMENOUN " '%s', not for current " GAMENOUN " '%s'\n", header + 0x14, machine->gamedrv->name);
|
||||
|
||||
/* enable compression */
|
||||
mame_fcompress(portdata->playback_file, TRUE);
|
||||
mame_fcompress(portdata->playback_file, FCOMPRESS_MEDIUM);
|
||||
|
||||
return basetime;
|
||||
}
|
||||
@ -4174,7 +4174,7 @@ static void record_init(running_machine *machine)
|
||||
mame_fwrite(portdata->record_file, header, sizeof(header));
|
||||
|
||||
/* enable compression */
|
||||
mame_fcompress(portdata->record_file, TRUE);
|
||||
mame_fcompress(portdata->record_file, FCOMPRESS_MEDIUM);
|
||||
}
|
||||
|
||||
|
||||
|
113
src/emu/mame.c
113
src/emu/mame.c
@ -1729,46 +1729,46 @@ static void handle_save(running_machine *machine)
|
||||
filerr = mame_fopen(mame->saveload_searchpath, astring_c(mame->saveload_pending_file), OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS, &file);
|
||||
if (filerr == FILERR_NONE)
|
||||
{
|
||||
int cpunum;
|
||||
astring *fullname = astring_dupc(mame_file_full_name(file));
|
||||
state_save_error staterr;
|
||||
|
||||
/* write the save state */
|
||||
if (state_save_save_begin(machine, file) != 0)
|
||||
staterr = state_save_write_file(machine, file);
|
||||
|
||||
/* handle the result */
|
||||
switch (staterr)
|
||||
{
|
||||
popmessage("Error: Unable to save state due to illegal registrations. See error.log for details.");
|
||||
mame_fclose(file);
|
||||
goto cancel;
|
||||
case STATERR_ILLEGAL_REGISTRATIONS:
|
||||
popmessage("Error: Unable to save state due to illegal registrations. See error.log for details.");
|
||||
break;
|
||||
|
||||
case STATERR_WRITE_ERROR:
|
||||
popmessage("Error: Unable to save state due to a write error. Verify there is enough disk space.");
|
||||
break;
|
||||
|
||||
case STATERR_NONE:
|
||||
if (!(machine->gamedrv->flags & GAME_SUPPORTS_SAVE))
|
||||
popmessage("State successfully saved.\nWarning: Save states are not officially supported for this game.");
|
||||
else
|
||||
popmessage("State successfully saved.");
|
||||
break;
|
||||
|
||||
default:
|
||||
popmessage("Error: Unknwon error during state save.");
|
||||
break;
|
||||
}
|
||||
|
||||
/* write the default tag */
|
||||
state_save_push_tag(0);
|
||||
state_save_save_continue(machine);
|
||||
state_save_pop_tag();
|
||||
|
||||
/* loop over CPUs */
|
||||
for (cpunum = 0; cpunum < ARRAY_LENGTH(machine->cpu); cpunum++)
|
||||
if (machine->cpu[cpunum] != NULL)
|
||||
{
|
||||
/* save the CPU data */
|
||||
state_save_push_tag(cpunum + 1);
|
||||
state_save_save_continue(machine);
|
||||
state_save_pop_tag();
|
||||
}
|
||||
|
||||
/* finish and close */
|
||||
state_save_save_finish(machine);
|
||||
/* close and perhaps delete the file */
|
||||
mame_fclose(file);
|
||||
|
||||
/* pop a warning if the game doesn't support saves */
|
||||
if (!(machine->gamedrv->flags & GAME_SUPPORTS_SAVE))
|
||||
popmessage("State successfully saved.\nWarning: Save states are not officially supported for this game.");
|
||||
else
|
||||
popmessage("State successfully saved.");
|
||||
if (staterr != STATERR_NONE)
|
||||
osd_rmfile(astring_c(fullname));
|
||||
astring_free(fullname);
|
||||
}
|
||||
else
|
||||
popmessage("Error: Failed to save state");
|
||||
popmessage("Error: Failed to create save state file.");
|
||||
|
||||
cancel:
|
||||
/* unschedule the save */
|
||||
cancel:
|
||||
astring_free(mame->saveload_pending_file);
|
||||
mame->saveload_searchpath = NULL;
|
||||
mame->saveload_pending_file = NULL;
|
||||
@ -1810,39 +1810,46 @@ static void handle_load(running_machine *machine)
|
||||
filerr = mame_fopen(mame->saveload_searchpath, astring_c(mame->saveload_pending_file), OPEN_FLAG_READ, &file);
|
||||
if (filerr == FILERR_NONE)
|
||||
{
|
||||
/* start loading */
|
||||
if (state_save_load_begin(machine, file) == 0)
|
||||
state_save_error staterr;
|
||||
|
||||
/* write the save state */
|
||||
staterr = state_save_read_file(machine, file);
|
||||
|
||||
/* handle the result */
|
||||
switch (staterr)
|
||||
{
|
||||
int cpunum;
|
||||
case STATERR_ILLEGAL_REGISTRATIONS:
|
||||
popmessage("Error: Unable to load state due to illegal registrations. See error.log for details.");
|
||||
break;
|
||||
|
||||
/* read tag 0 */
|
||||
state_save_push_tag(0);
|
||||
state_save_load_continue(machine);
|
||||
state_save_pop_tag();
|
||||
case STATERR_INVALID_HEADER:
|
||||
popmessage("Error: Unable to load state due to an invalid header. Make sure the save state is correct for this game.");
|
||||
break;
|
||||
|
||||
/* loop over CPUs */
|
||||
for (cpunum = 0; cpunum < ARRAY_LENGTH(machine->cpu); cpunum++)
|
||||
if (machine->cpu[cpunum] != NULL)
|
||||
{
|
||||
/* load the CPU data */
|
||||
state_save_push_tag(cpunum + 1);
|
||||
state_save_load_continue(machine);
|
||||
state_save_pop_tag();
|
||||
}
|
||||
case STATERR_READ_ERROR:
|
||||
popmessage("Error: Unable to load state due to a read error (file is likely corrupt).");
|
||||
break;
|
||||
|
||||
/* finish and close */
|
||||
state_save_load_finish(machine);
|
||||
popmessage("State successfully loaded.");
|
||||
case STATERR_NONE:
|
||||
if (!(machine->gamedrv->flags & GAME_SUPPORTS_SAVE))
|
||||
popmessage("State successfully loaded.\nWarning: Save states are not officially supported for this game.");
|
||||
else
|
||||
popmessage("State successfully loaded.");
|
||||
break;
|
||||
|
||||
default:
|
||||
popmessage("Error: Unknwon error during state load.");
|
||||
break;
|
||||
}
|
||||
else
|
||||
popmessage("Error: Failed to load state");
|
||||
|
||||
/* close the file */
|
||||
mame_fclose(file);
|
||||
}
|
||||
else
|
||||
popmessage("Error: Failed to load state");
|
||||
popmessage("Error: Failed to open save state file.");
|
||||
|
||||
cancel:
|
||||
/* unschedule the load */
|
||||
cancel:
|
||||
astring_free(mame->saveload_pending_file);
|
||||
mame->saveload_pending_file = NULL;
|
||||
mame->saveload_schedule_callback = NULL;
|
||||
|
483
src/emu/state.c
483
src/emu/state.c
@ -11,12 +11,15 @@
|
||||
|
||||
Save state file format:
|
||||
|
||||
0.. 7 'MAMESAVE"
|
||||
8 Format version (this is format 1)
|
||||
9 Flags
|
||||
a..13 Game name padded with \0
|
||||
14..17 Signature
|
||||
18..end Save game data
|
||||
00..07 'MAMESAVE'
|
||||
08 Format version (this is format 2)
|
||||
09 Flags
|
||||
0A..1B Game name padded with \0
|
||||
1C..1F Signature
|
||||
20..end Save game data (compressed)
|
||||
|
||||
Data is always written as native-endian.
|
||||
Data is converted from the endiannness it was written upon load.
|
||||
|
||||
***************************************************************************/
|
||||
|
||||
@ -40,9 +43,8 @@
|
||||
CONSTANTS
|
||||
***************************************************************************/
|
||||
|
||||
#define SAVE_VERSION 1
|
||||
|
||||
#define TAG_STACK_SIZE 4
|
||||
#define SAVE_VERSION 2
|
||||
#define HEADER_SIZE 32
|
||||
|
||||
/* Available flags */
|
||||
enum
|
||||
@ -65,7 +67,6 @@ struct _state_entry
|
||||
astring * name; /* full name */
|
||||
UINT8 typesize; /* size of the raw data type */
|
||||
UINT32 typecount; /* number of items */
|
||||
int tag; /* saving tag */
|
||||
UINT32 offset; /* offset within the final structure */
|
||||
};
|
||||
|
||||
@ -76,7 +77,6 @@ struct _state_callback
|
||||
state_callback * next; /* pointer to next entry */
|
||||
running_machine * machine; /* pointer back to the owning machine */
|
||||
void * param; /* function parameter */
|
||||
int tag; /* saving tag */
|
||||
union
|
||||
{
|
||||
state_presave_func presave; /* presave callback */
|
||||
@ -106,11 +106,6 @@ struct _state_private
|
||||
GLOBAL VARIABLES
|
||||
***************************************************************************/
|
||||
|
||||
/* this stuff goes away when CPU cores are fully pointer-ized */
|
||||
static int ss_tag_stack[TAG_STACK_SIZE];
|
||||
static int ss_tag_stack_index;
|
||||
static int ss_current_tag;
|
||||
|
||||
#ifdef MESS
|
||||
static const char ss_magic_num[8] = { 'M', 'E', 'S', 'S', 'S', 'A', 'V', 'E' };
|
||||
#else
|
||||
@ -120,14 +115,42 @@ static const char ss_magic_num[8] = { 'M', 'A', 'M', 'E', 'S', 'A', 'V', 'E' };
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
FUNCTION PROTOTYPES
|
||||
INLINE FUNCTIONS
|
||||
***************************************************************************/
|
||||
|
||||
static void ss_c2(UINT8 *, UINT32);
|
||||
static void ss_c4(UINT8 *, UINT32);
|
||||
static void ss_c8(UINT8 *, UINT32);
|
||||
/*-------------------------------------------------
|
||||
flip_data - reverse the endianness of a
|
||||
block of data
|
||||
-------------------------------------------------*/
|
||||
|
||||
static void (*const ss_conv[])(UINT8 *, UINT32) = { 0, 0, ss_c2, 0, ss_c4, 0, 0, 0, ss_c8 };
|
||||
INLINE void flip_data(state_entry *entry)
|
||||
{
|
||||
UINT16 *data16;
|
||||
UINT32 *data32;
|
||||
UINT64 *data64;
|
||||
int count;
|
||||
|
||||
switch (entry->typesize)
|
||||
{
|
||||
case 2:
|
||||
data16 = entry->data;
|
||||
for (count = 0; count < entry->typecount; count++)
|
||||
data16[count] = FLIPENDIAN_INT16(data16[count]);
|
||||
break;
|
||||
|
||||
case 4:
|
||||
data32 = entry->data;
|
||||
for (count = 0; count < entry->typecount; count++)
|
||||
data32[count] = FLIPENDIAN_INT32(data32[count]);
|
||||
break;
|
||||
|
||||
case 8:
|
||||
data64 = entry->data;
|
||||
for (count = 0; count < entry->typecount; count++)
|
||||
data64[count] = FLIPENDIAN_INT64(data64[count]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -158,7 +181,7 @@ int state_save_get_reg_count(running_machine *machine)
|
||||
state_entry *entry;
|
||||
int count = 0;
|
||||
|
||||
/* iterate over entries with matching tags */
|
||||
/* count entries */
|
||||
for (entry = global->entrylist; entry != NULL; entry = entry->next)
|
||||
count++;
|
||||
|
||||
@ -167,38 +190,6 @@ int state_save_get_reg_count(running_machine *machine)
|
||||
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
TAGGING
|
||||
***************************************************************************/
|
||||
|
||||
/*-------------------------------------------------
|
||||
state_save_push_tag - push the current tag
|
||||
onto the stack and set a new tag
|
||||
-------------------------------------------------*/
|
||||
|
||||
void state_save_push_tag(int tag)
|
||||
{
|
||||
if (ss_tag_stack_index == TAG_STACK_SIZE - 1)
|
||||
fatalerror("state_save tag stack overflow");
|
||||
ss_tag_stack[ss_tag_stack_index++] = ss_current_tag;
|
||||
ss_current_tag = tag;
|
||||
}
|
||||
|
||||
|
||||
/*-------------------------------------------------
|
||||
state_save_pop_tag - pop the tag from the top
|
||||
of the stack
|
||||
-------------------------------------------------*/
|
||||
|
||||
void state_save_pop_tag(void)
|
||||
{
|
||||
if (ss_tag_stack_index == 0)
|
||||
fatalerror("state_save tag stack underflow");
|
||||
ss_current_tag = ss_tag_stack[--ss_tag_stack_index];
|
||||
}
|
||||
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
REGISTRATION HANDLING
|
||||
***************************************************************************/
|
||||
@ -254,9 +245,9 @@ void state_save_register_memory(running_machine *machine, const char *module, co
|
||||
/* create the full name */
|
||||
totalname = astring_alloc();
|
||||
if (tag != NULL)
|
||||
astring_printf(totalname, "%X/%s/%s/%X/%s", ss_current_tag, module, tag, index, name);
|
||||
astring_printf(totalname, "%s/%s/%X/%s", module, tag, index, name);
|
||||
else
|
||||
astring_printf(totalname, "%X/%s/%X/%s", ss_current_tag, module, index, name);
|
||||
astring_printf(totalname, "%s/%X/%s", module, index, name);
|
||||
|
||||
/* look for duplicates and an entry to insert in front of */
|
||||
for (entryptr = &global->entrylist; *entryptr != NULL; entryptr = &(*entryptr)->next)
|
||||
@ -267,8 +258,8 @@ void state_save_register_memory(running_machine *machine, const char *module, co
|
||||
break;
|
||||
|
||||
/* error if we are equal */
|
||||
if ((*entryptr)->tag == ss_current_tag && cmpval == 0)
|
||||
fatalerror("Duplicate save state registration entry (%d, %s)", ss_current_tag, astring_c(totalname));
|
||||
if (cmpval == 0)
|
||||
fatalerror("Duplicate save state registration entry (%s)", astring_c(totalname));
|
||||
}
|
||||
|
||||
/* didn't find one; allocate a new one */
|
||||
@ -283,7 +274,6 @@ void state_save_register_memory(running_machine *machine, const char *module, co
|
||||
(*entryptr)->name = totalname;
|
||||
(*entryptr)->typesize = valsize;
|
||||
(*entryptr)->typecount = valcount;
|
||||
(*entryptr)->tag = ss_current_tag;
|
||||
restrack_register_object(OBJTYPE_STATEREG, *entryptr, 0, __FILE__, __LINE__);
|
||||
}
|
||||
|
||||
@ -320,8 +310,8 @@ void state_save_register_presave(running_machine *machine, state_presave_func fu
|
||||
|
||||
/* scan for duplicates and push through to the end */
|
||||
for (cbptr = &global->prefunclist; *cbptr != NULL; cbptr = &(*cbptr)->next)
|
||||
if ((*cbptr)->func.presave == func && (*cbptr)->param == param && (*cbptr)->tag == ss_current_tag)
|
||||
fatalerror("Duplicate save state function (%d, %p, %p)", ss_current_tag, param, func);
|
||||
if ((*cbptr)->func.presave == func && (*cbptr)->param == param)
|
||||
fatalerror("Duplicate save state function (%p, %p)", param, func);
|
||||
|
||||
/* allocate a new entry */
|
||||
*cbptr = malloc_or_die(sizeof(state_callback));
|
||||
@ -331,7 +321,6 @@ void state_save_register_presave(running_machine *machine, state_presave_func fu
|
||||
(*cbptr)->machine = machine;
|
||||
(*cbptr)->func.presave = func;
|
||||
(*cbptr)->param = param;
|
||||
(*cbptr)->tag = ss_current_tag;
|
||||
restrack_register_object(OBJTYPE_STATEREG, *cbptr, 1, __FILE__, __LINE__);
|
||||
}
|
||||
|
||||
@ -352,8 +341,8 @@ void state_save_register_postload(running_machine *machine, state_postload_func
|
||||
|
||||
/* scan for duplicates and push through to the end */
|
||||
for (cbptr = &global->postfunclist; *cbptr != NULL; cbptr = &(*cbptr)->next)
|
||||
if ((*cbptr)->func.postload == func && (*cbptr)->param == param && (*cbptr)->tag == ss_current_tag)
|
||||
fatalerror("Duplicate save state function (%d, %p, %p)", ss_current_tag, param, func);
|
||||
if ((*cbptr)->func.postload == func && (*cbptr)->param == param)
|
||||
fatalerror("Duplicate save state function (%p, %p)", param, func);
|
||||
|
||||
/* allocate a new entry */
|
||||
*cbptr = malloc_or_die(sizeof(state_callback));
|
||||
@ -363,7 +352,6 @@ void state_save_register_postload(running_machine *machine, state_postload_func
|
||||
(*cbptr)->machine = machine;
|
||||
(*cbptr)->func.postload = func;
|
||||
(*cbptr)->param = param;
|
||||
(*cbptr)->tag = ss_current_tag;
|
||||
restrack_register_object(OBJTYPE_STATEREG, *cbptr, 2, __FILE__, __LINE__);
|
||||
}
|
||||
|
||||
@ -447,83 +435,10 @@ void state_destructor(void *ptr, size_t size)
|
||||
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
ENDIAN CONVERSION
|
||||
***************************************************************************/
|
||||
|
||||
/*-------------------------------------------------
|
||||
ss_c2 - byte swap an array of 16-bit data
|
||||
-------------------------------------------------*/
|
||||
|
||||
static void ss_c2(UINT8 *data, UINT32 size)
|
||||
{
|
||||
UINT16 *convert = (UINT16 *)data;
|
||||
unsigned i;
|
||||
|
||||
for (i = 0; i < size; i++)
|
||||
convert[i] = FLIPENDIAN_INT16(convert[i]);
|
||||
}
|
||||
|
||||
|
||||
/*-------------------------------------------------
|
||||
ss_c4 - byte swap an array of 32-bit data
|
||||
-------------------------------------------------*/
|
||||
|
||||
static void ss_c4(UINT8 *data, UINT32 size)
|
||||
{
|
||||
UINT32 *convert = (UINT32 *)data;
|
||||
unsigned i;
|
||||
|
||||
for (i = 0; i < size; i++)
|
||||
convert[i] = FLIPENDIAN_INT32(convert[i]);
|
||||
}
|
||||
|
||||
|
||||
/*-------------------------------------------------
|
||||
ss_c8 - byte swap an array of 64-bit data
|
||||
-------------------------------------------------*/
|
||||
|
||||
static void ss_c8(UINT8 *data, UINT32 size)
|
||||
{
|
||||
UINT64 *convert = (UINT64 *)data;
|
||||
unsigned i;
|
||||
|
||||
for (i = 0; i < size; i++)
|
||||
convert[i] = FLIPENDIAN_INT64(convert[i]);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
PROCESSING HELPERS
|
||||
***************************************************************************/
|
||||
|
||||
/*-------------------------------------------------
|
||||
compute_size_and_offsets - compute the total
|
||||
size and offsets of each individual item
|
||||
-------------------------------------------------*/
|
||||
|
||||
static int compute_size_and_offsets(state_private *global)
|
||||
{
|
||||
state_entry *entry;
|
||||
int total_size;
|
||||
|
||||
/* start with the header size */
|
||||
total_size = 0x18;
|
||||
|
||||
/* iterate over entries */
|
||||
for (entry = global->entrylist; entry; entry = entry->next)
|
||||
{
|
||||
/* note the offset and accumulate a total size */
|
||||
entry->offset = total_size;
|
||||
total_size += entry->typesize * entry->typecount;
|
||||
}
|
||||
|
||||
/* return the total size */
|
||||
return total_size;
|
||||
}
|
||||
|
||||
|
||||
/*-------------------------------------------------
|
||||
get_signature - compute the signature, which
|
||||
is a CRC over the structure of the data
|
||||
@ -536,7 +451,7 @@ static UINT32 get_signature(running_machine *machine)
|
||||
UINT32 crc = 0;
|
||||
|
||||
/* iterate over entries */
|
||||
for (entry = global->entrylist; entry; entry = entry->next)
|
||||
for (entry = global->entrylist; entry != NULL; entry = entry->next)
|
||||
{
|
||||
UINT32 temp[2];
|
||||
|
||||
@ -546,7 +461,7 @@ static UINT32 get_signature(running_machine *machine)
|
||||
/* add the type and size to the CRC */
|
||||
temp[0] = LITTLE_ENDIANIZE_INT32(entry->typecount);
|
||||
temp[1] = LITTLE_ENDIANIZE_INT32(entry->typesize);
|
||||
crc = crc32(crc, (UINT8 *)&temp[0], 8);
|
||||
crc = crc32(crc, (UINT8 *)&temp[0], sizeof(temp));
|
||||
}
|
||||
|
||||
return crc;
|
||||
@ -555,7 +470,7 @@ static UINT32 get_signature(running_machine *machine)
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
STATE FILE VALIDATION
|
||||
SAVE STATE FILE PROCESSING
|
||||
***************************************************************************/
|
||||
|
||||
/*-------------------------------------------------
|
||||
@ -563,46 +478,45 @@ static UINT32 get_signature(running_machine *machine)
|
||||
header
|
||||
-------------------------------------------------*/
|
||||
|
||||
static int validate_header(const UINT8 *header, const char *gamename, UINT32 signature,
|
||||
static state_save_error validate_header(const UINT8 *header, const char *gamename, UINT32 signature,
|
||||
void (CLIB_DECL *errormsg)(const char *fmt, ...), const char *error_prefix)
|
||||
{
|
||||
/* check magic number */
|
||||
if (memcmp(header, ss_magic_num, 8))
|
||||
{
|
||||
if (errormsg)
|
||||
errormsg("%sThis is not a " APPNAME " save file", error_prefix);
|
||||
return -1;
|
||||
if (errormsg != NULL)
|
||||
(*errormsg)("%sThis is not a " APPNAME " save file", error_prefix);
|
||||
return STATERR_INVALID_HEADER;
|
||||
}
|
||||
|
||||
/* check save state version */
|
||||
if (header[8] != SAVE_VERSION)
|
||||
{
|
||||
if (errormsg)
|
||||
errormsg("%sWrong version in save file (%d, 1 expected)", error_prefix, header[8]);
|
||||
return -1;
|
||||
if (errormsg != NULL)
|
||||
(*errormsg)("%sWrong version in save file (version %d, expected %d)", error_prefix, header[8], SAVE_VERSION);
|
||||
return STATERR_INVALID_HEADER;
|
||||
}
|
||||
|
||||
/* check gamename, if we were asked to */
|
||||
if (gamename && strcmp(gamename, (const char *)&header[10]))
|
||||
if (gamename != NULL && strncmp(gamename, (const char *)&header[0x0a], 0x1c - 0x0a))
|
||||
{
|
||||
if (errormsg)
|
||||
errormsg("%s'%s' is not a valid savestate file for game '%s'.", error_prefix, gamename);
|
||||
return -1;
|
||||
if (errormsg != NULL)
|
||||
(*errormsg)("%s'File is not a valid savestate file for game '%s'.", error_prefix, gamename);
|
||||
return STATERR_INVALID_HEADER;
|
||||
}
|
||||
|
||||
/* check signature, if we were asked to */
|
||||
if (signature)
|
||||
if (signature != 0)
|
||||
{
|
||||
UINT32 rawsig = *(UINT32 *)&header[0x14];
|
||||
UINT32 filesig = LITTLE_ENDIANIZE_INT32(rawsig);
|
||||
if (signature != filesig)
|
||||
UINT32 rawsig = *(UINT32 *)&header[0x1c];
|
||||
if (signature != LITTLE_ENDIANIZE_INT32(rawsig))
|
||||
{
|
||||
if (errormsg)
|
||||
errormsg("%sIncompatible save file (signature %08x, expected %08x)", error_prefix, filesig, signature);
|
||||
return -1;
|
||||
if (errormsg != NULL)
|
||||
(*errormsg)("%sIncompatible save file (signature %08x, expected %08x)", error_prefix, LITTLE_ENDIANIZE_INT32(rawsig), signature);
|
||||
return STATERR_INVALID_HEADER;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
return STATERR_NONE;
|
||||
}
|
||||
|
||||
|
||||
@ -611,22 +525,23 @@ static int validate_header(const UINT8 *header, const char *gamename, UINT32 sig
|
||||
a valid save state
|
||||
-------------------------------------------------*/
|
||||
|
||||
int state_save_check_file(running_machine *machine, mame_file *file, const char *gamename, void (CLIB_DECL *errormsg)(const char *fmt, ...))
|
||||
state_save_error state_save_check_file(running_machine *machine, mame_file *file, const char *gamename, void (CLIB_DECL *errormsg)(const char *fmt, ...))
|
||||
{
|
||||
UINT8 header[HEADER_SIZE];
|
||||
UINT32 signature = 0;
|
||||
UINT8 header[0x18];
|
||||
|
||||
/* if we want to validate the signature, compute it */
|
||||
if (machine != NULL)
|
||||
signature = get_signature(machine);
|
||||
|
||||
/* seek to the beginning and read the header */
|
||||
mame_fcompress(file, FCOMPRESS_NONE);
|
||||
mame_fseek(file, 0, SEEK_SET);
|
||||
if (mame_fread(file, header, sizeof(header)) != sizeof(header))
|
||||
{
|
||||
if (errormsg)
|
||||
errormsg("Could not read " APPNAME " save file header");
|
||||
return -1;
|
||||
if (errormsg != NULL)
|
||||
(*errormsg)("Could not read " APPNAME " save file header");
|
||||
return STATERR_READ_ERROR;
|
||||
}
|
||||
|
||||
/* let the generic header check work out the rest */
|
||||
@ -634,215 +549,109 @@ int state_save_check_file(running_machine *machine, mame_file *file, const char
|
||||
}
|
||||
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
SAVE STATE PROCESSING
|
||||
***************************************************************************/
|
||||
|
||||
/*-------------------------------------------------
|
||||
state_save_save_begin - begin the process of
|
||||
saving
|
||||
state_save_write_file - writes the data to
|
||||
a file
|
||||
-------------------------------------------------*/
|
||||
|
||||
int state_save_save_begin(running_machine *machine, mame_file *file)
|
||||
state_save_error state_save_write_file(running_machine *machine, mame_file *file)
|
||||
{
|
||||
state_private *global = machine->state_data;
|
||||
UINT32 signature = get_signature(machine);
|
||||
UINT8 header[HEADER_SIZE];
|
||||
state_callback *func;
|
||||
state_entry *entry;
|
||||
|
||||
/* if we have illegal registrations, return an error */
|
||||
if (global->illegal_regs > 0)
|
||||
return 1;
|
||||
return STATERR_ILLEGAL_REGISTRATIONS;
|
||||
|
||||
LOG(("Beginning save\n"));
|
||||
global->iofile = file;
|
||||
/* generate the header */
|
||||
memcpy(&header[0], ss_magic_num, 8);
|
||||
header[8] = SAVE_VERSION;
|
||||
#ifdef LSB_FIRST
|
||||
header[9] = 0;
|
||||
#else
|
||||
header[9] = SS_MSB_FIRST;
|
||||
#endif
|
||||
strncpy((char *)&header[0x0a], machine->gamedrv->name, 0x1c - 0x0a);
|
||||
*(UINT32 *)&header[0x1c] = LITTLE_ENDIANIZE_INT32(signature);
|
||||
|
||||
/* compute the total dump size and the offsets of each element */
|
||||
global->ioarraysize = compute_size_and_offsets(global);
|
||||
LOG((" total size %u\n", global->ioarraysize));
|
||||
|
||||
/* allocate memory for the array */
|
||||
global->ioarray = malloc_or_die(global->ioarraysize);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*-------------------------------------------------
|
||||
state_save_save_continue - save within the
|
||||
current tag
|
||||
-------------------------------------------------*/
|
||||
|
||||
void state_save_save_continue(running_machine *machine)
|
||||
{
|
||||
state_private *global = machine->state_data;
|
||||
state_entry *entry;
|
||||
state_callback *func;
|
||||
int count = 0;
|
||||
|
||||
LOG(("Saving tag %d\n", ss_current_tag));
|
||||
/* write the header and turn on compression for the rest of the file */
|
||||
mame_fcompress(file, FCOMPRESS_NONE);
|
||||
mame_fseek(file, 0, SEEK_SET);
|
||||
if (mame_fwrite(file, header, sizeof(header)) != sizeof(header))
|
||||
return STATERR_WRITE_ERROR;
|
||||
mame_fcompress(file, FCOMPRESS_MEDIUM);
|
||||
|
||||
/* call the pre-save functions */
|
||||
LOG((" calling pre-save functions\n"));
|
||||
|
||||
/* iterate over the list of functions */
|
||||
for (func = global->prefunclist; func != NULL; func = func->next)
|
||||
if (func->tag == ss_current_tag)
|
||||
{
|
||||
count++;
|
||||
(*func->func.presave)(machine, func->param);
|
||||
}
|
||||
LOG((" %d functions called\n", count));
|
||||
(*func->func.presave)(machine, func->param);
|
||||
|
||||
/* then copy in all the data */
|
||||
LOG((" copying data\n"));
|
||||
|
||||
/* iterate over entries with matching tags */
|
||||
/* then write all the data */
|
||||
for (entry = global->entrylist; entry != NULL; entry = entry->next)
|
||||
if (entry->tag == ss_current_tag)
|
||||
{
|
||||
memcpy(global->ioarray + entry->offset, entry->data, entry->typesize * entry->typecount);
|
||||
LOG((" %s: %x..%x\n", astring_c(entry->name), entry->offset, entry->offset + entry->typesize * entry->typecount - 1));
|
||||
}
|
||||
{
|
||||
UINT32 totalsize = entry->typesize * entry->typecount;
|
||||
if (mame_fwrite(file, entry->data, totalsize) != totalsize)
|
||||
return STATERR_WRITE_ERROR;
|
||||
}
|
||||
return STATERR_NONE;
|
||||
}
|
||||
|
||||
|
||||
/*-------------------------------------------------
|
||||
state_save_save_finish - finish saving the
|
||||
file by writing the header and closing
|
||||
state_save_read_file - read the data from a
|
||||
file
|
||||
-------------------------------------------------*/
|
||||
|
||||
void state_save_save_finish(running_machine *machine)
|
||||
state_save_error state_save_read_file(running_machine *machine, mame_file *file)
|
||||
{
|
||||
state_private *global = machine->state_data;
|
||||
UINT32 signature;
|
||||
UINT8 flags = 0;
|
||||
UINT32 signature = get_signature(machine);
|
||||
UINT8 header[HEADER_SIZE];
|
||||
state_callback *func;
|
||||
state_entry *entry;
|
||||
int flip;
|
||||
|
||||
LOG(("Finishing save\n"));
|
||||
/* if we have illegal registrations, return an error */
|
||||
if (global->illegal_regs > 0)
|
||||
return STATERR_ILLEGAL_REGISTRATIONS;
|
||||
|
||||
/* compute the flags */
|
||||
#ifndef LSB_FIRST
|
||||
flags |= SS_MSB_FIRST;
|
||||
#endif
|
||||
|
||||
/* build up the header */
|
||||
memcpy(global->ioarray, ss_magic_num, 8);
|
||||
global->ioarray[8] = SAVE_VERSION;
|
||||
global->ioarray[9] = flags;
|
||||
memset(global->ioarray+0xa, 0, 10);
|
||||
strcpy((char *)global->ioarray+0xa, machine->gamedrv->name);
|
||||
|
||||
/* copy in the signature */
|
||||
signature = get_signature(machine);
|
||||
*(UINT32 *)&global->ioarray[0x14] = LITTLE_ENDIANIZE_INT32(signature);
|
||||
|
||||
/* write the file */
|
||||
mame_fwrite(global->iofile, global->ioarray, global->ioarraysize);
|
||||
|
||||
/* free memory and reset the global states */
|
||||
free(global->ioarray);
|
||||
global->ioarray = NULL;
|
||||
global->ioarraysize = 0;
|
||||
global->iofile = NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
LOAD STATE PROCESSING
|
||||
***************************************************************************/
|
||||
|
||||
/*-------------------------------------------------
|
||||
state_save_load_begin - begin the process
|
||||
of loading the state
|
||||
-------------------------------------------------*/
|
||||
|
||||
int state_save_load_begin(running_machine *machine, mame_file *file)
|
||||
{
|
||||
state_private *global = machine->state_data;
|
||||
|
||||
LOG(("Beginning load\n"));
|
||||
|
||||
/* read the file into memory */
|
||||
global->ioarraysize = mame_fsize(file);
|
||||
global->ioarray = malloc_or_die(global->ioarraysize);
|
||||
global->iofile = file;
|
||||
mame_fread(global->iofile, global->ioarray, global->ioarraysize);
|
||||
/* read the header and turn on compression for the rest of the file */
|
||||
mame_fcompress(file, FCOMPRESS_NONE);
|
||||
mame_fseek(file, 0, SEEK_SET);
|
||||
if (mame_fread(file, header, sizeof(header)) != sizeof(header))
|
||||
return STATERR_READ_ERROR;
|
||||
mame_fcompress(file, FCOMPRESS_MEDIUM);
|
||||
|
||||
/* verify the header and report an error if it doesn't match */
|
||||
if (validate_header(global->ioarray, NULL, get_signature(machine), popmessage, "Error: "))
|
||||
{
|
||||
free(global->ioarray);
|
||||
global->ioarray = NULL;
|
||||
global->ioarraysize = 0;
|
||||
global->iofile = NULL;
|
||||
return 1;
|
||||
}
|
||||
if (validate_header(header, machine->gamedrv->name, signature, popmessage, "Error: ") != STATERR_NONE)
|
||||
return STATERR_INVALID_HEADER;
|
||||
|
||||
/* compute the total size and offset of all the entries */
|
||||
compute_size_and_offsets(global);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*-------------------------------------------------
|
||||
state_save_load_continue - load all state in
|
||||
the current tag
|
||||
-------------------------------------------------*/
|
||||
|
||||
void state_save_load_continue(running_machine *machine)
|
||||
{
|
||||
state_private *global = machine->state_data;
|
||||
state_entry *entry;
|
||||
state_callback *func;
|
||||
int need_convert;
|
||||
int count = 0;
|
||||
|
||||
/* first determine whether or not we need to convert the endianness of the data */
|
||||
/* determine whether or not to flip the data when done */
|
||||
#ifdef LSB_FIRST
|
||||
need_convert = (global->ioarray[9] & SS_MSB_FIRST) != 0;
|
||||
flip = ((header[9] & SS_MSB_FIRST) != 0);
|
||||
#else
|
||||
need_convert = (global->ioarray[9] & SS_MSB_FIRST) == 0;
|
||||
flip = ((header[9] & SS_MSB_FIRST) == 0);
|
||||
#endif
|
||||
|
||||
LOG(("Loading tag %d\n", ss_current_tag));
|
||||
LOG((" copying data\n"));
|
||||
|
||||
/* iterate over entries with matching tags */
|
||||
/* read all the data, flipping if necessary */
|
||||
for (entry = global->entrylist; entry != NULL; entry = entry->next)
|
||||
if (entry->tag == ss_current_tag)
|
||||
{
|
||||
memcpy(entry->data, global->ioarray + entry->offset, entry->typesize * entry->typecount);
|
||||
if (need_convert && ss_conv[entry->typesize])
|
||||
(*ss_conv[entry->typesize])(entry->data, entry->typecount);
|
||||
LOG((" %s: %x..%x\n", astring_c(entry->name), entry->offset, entry->offset + entry->typesize * entry->typecount - 1));
|
||||
}
|
||||
{
|
||||
UINT32 totalsize = entry->typesize * entry->typecount;
|
||||
if (mame_fread(file, entry->data, totalsize) != totalsize)
|
||||
return STATERR_READ_ERROR;
|
||||
|
||||
/* handle flipping */
|
||||
if (flip)
|
||||
flip_data(entry);
|
||||
}
|
||||
|
||||
/* call the post-load functions */
|
||||
LOG((" calling post-load functions\n"));
|
||||
for (func = global->postfunclist; func != NULL; func = func->next)
|
||||
if (func->tag == ss_current_tag)
|
||||
{
|
||||
count++;
|
||||
(*func->func.postload)(machine, func->param);
|
||||
}
|
||||
LOG((" %d functions called\n", count));
|
||||
}
|
||||
(*func->func.postload)(machine, func->param);
|
||||
|
||||
|
||||
/*-------------------------------------------------
|
||||
state_save_load_finish - complete the process
|
||||
of loading the state
|
||||
-------------------------------------------------*/
|
||||
|
||||
void state_save_load_finish(running_machine *machine)
|
||||
{
|
||||
state_private *global = machine->state_data;
|
||||
|
||||
LOG(("Finishing load\n"));
|
||||
|
||||
/* free memory and reset the global states */
|
||||
free(global->ioarray);
|
||||
global->ioarray = NULL;
|
||||
global->ioarraysize = 0;
|
||||
global->iofile = NULL;
|
||||
return STATERR_NONE;
|
||||
}
|
||||
|
||||
|
||||
|
@ -27,6 +27,22 @@ typedef void (*state_postload_func)(running_machine *machine, void *param);
|
||||
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
CONSTANTS
|
||||
***************************************************************************/
|
||||
|
||||
enum _state_save_error
|
||||
{
|
||||
STATERR_NONE,
|
||||
STATERR_ILLEGAL_REGISTRATIONS,
|
||||
STATERR_INVALID_HEADER,
|
||||
STATERR_READ_ERROR,
|
||||
STATERR_WRITE_ERROR
|
||||
};
|
||||
typedef enum _state_save_error state_save_error;
|
||||
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
MACROS
|
||||
***************************************************************************/
|
||||
@ -124,16 +140,6 @@ int state_save_get_reg_count(running_machine *machine);
|
||||
|
||||
|
||||
|
||||
/* ----- tagging ----- */
|
||||
|
||||
/* push the current tag onto the stack and set a new tag */
|
||||
void state_save_push_tag(int tag);
|
||||
|
||||
/* pop the tag from the top of the stack */
|
||||
void state_save_pop_tag(void);
|
||||
|
||||
|
||||
|
||||
/* ----- registration handling ----- */
|
||||
|
||||
/* allow/disallow registrations to happen (called by the core) */
|
||||
@ -167,36 +173,16 @@ void state_destructor(void *ptr, size_t size);
|
||||
|
||||
|
||||
|
||||
/* ----- state file validation ----- */
|
||||
/* ----- save state file processing ----- */
|
||||
|
||||
/* check if a file is a valid save state */
|
||||
int state_save_check_file(running_machine *machine, mame_file *file, const char *gamename, void (CLIB_DECL *errormsg)(const char *fmt, ...));
|
||||
state_save_error state_save_check_file(running_machine *machine, mame_file *file, const char *gamename, void (CLIB_DECL *errormsg)(const char *fmt, ...));
|
||||
|
||||
/* write out the save state file */
|
||||
state_save_error state_save_write_file(running_machine *machine, mame_file *file);
|
||||
|
||||
|
||||
/* ----- save state processing ----- */
|
||||
|
||||
/* begin the process of saving */
|
||||
int state_save_save_begin(running_machine *machine, mame_file *file);
|
||||
|
||||
/* save within the current tag */
|
||||
void state_save_save_continue(running_machine *machine);
|
||||
|
||||
/* finish saving the file by writing the header and closing */
|
||||
void state_save_save_finish(running_machine *machine);
|
||||
|
||||
|
||||
|
||||
/* ----- load state processing ----- */
|
||||
|
||||
/* begin the process of loading the state */
|
||||
int state_save_load_begin(running_machine *machine, mame_file *file);
|
||||
|
||||
/* load all state in the current tag */
|
||||
void state_save_load_continue(running_machine *machine);
|
||||
|
||||
/* complete the process of loading the state */
|
||||
void state_save_load_finish(running_machine *machine);
|
||||
/* read in a save state file */
|
||||
state_save_error state_save_read_file(running_machine *machine, mame_file *file);
|
||||
|
||||
|
||||
|
||||
|
@ -296,11 +296,9 @@ void timer_init(running_machine *machine)
|
||||
global->callback_timer_modified = FALSE;
|
||||
|
||||
/* register with the save state system */
|
||||
state_save_push_tag(0);
|
||||
state_save_register_item(machine, "timer", NULL, 0, global->basetime.seconds);
|
||||
state_save_register_item(machine, "timer", NULL, 0, global->basetime.attoseconds);
|
||||
state_save_register_postload(machine, timer_postload, NULL);
|
||||
state_save_pop_tag();
|
||||
|
||||
/* initialize the lists */
|
||||
global->activelist = NULL;
|
||||
@ -523,7 +521,6 @@ static void timer_register_save(emu_timer *timer)
|
||||
count++;
|
||||
|
||||
/* use different instances to differentiate the bits */
|
||||
state_save_push_tag(0);
|
||||
state_save_register_item(timer->machine, "timer", timer->func, count, timer->param);
|
||||
state_save_register_item(timer->machine, "timer", timer->func, count, timer->enabled);
|
||||
state_save_register_item(timer->machine, "timer", timer->func, count, timer->period.seconds);
|
||||
@ -532,7 +529,6 @@ static void timer_register_save(emu_timer *timer)
|
||||
state_save_register_item(timer->machine, "timer", timer->func, count, timer->start.attoseconds);
|
||||
state_save_register_item(timer->machine, "timer", timer->func, count, timer->expire.seconds);
|
||||
state_save_register_item(timer->machine, "timer", timer->func, count, timer->expire.attoseconds);
|
||||
state_save_pop_tag();
|
||||
}
|
||||
|
||||
|
||||
|
@ -45,10 +45,8 @@ void watchdog_init(running_machine *machine)
|
||||
add_reset_callback(machine, watchdog_internal_reset);
|
||||
|
||||
/* save some stuff in the default tag */
|
||||
state_save_push_tag(0);
|
||||
state_save_register_item(machine, "watchdog", NULL, 0, watchdog_enabled);
|
||||
state_save_register_item(machine, "watchdog", NULL, 0, watchdog_counter);
|
||||
state_save_pop_tag();
|
||||
}
|
||||
|
||||
|
||||
|
@ -213,7 +213,7 @@ void core_fclose(core_file *file)
|
||||
{
|
||||
/* close files and free memory */
|
||||
if (file->zdata != NULL)
|
||||
core_fcompress(file, FALSE);
|
||||
core_fcompress(file, FCOMPRESS_NONE);
|
||||
if (file->file != NULL)
|
||||
osd_close(file->file);
|
||||
if (file->data != NULL && file->data_allocated)
|
||||
@ -224,10 +224,11 @@ void core_fclose(core_file *file)
|
||||
|
||||
/*-------------------------------------------------
|
||||
core_fcompress - enable/disable streaming file
|
||||
compression via zlib
|
||||
compression via zlib; level is 0 to disable
|
||||
compression, or up to 9 for max compression
|
||||
-------------------------------------------------*/
|
||||
|
||||
file_error core_fcompress(core_file *file, int compress)
|
||||
file_error core_fcompress(core_file *file, int level)
|
||||
{
|
||||
file_error result = FILERR_NONE;
|
||||
|
||||
@ -236,7 +237,7 @@ file_error core_fcompress(core_file *file, int compress)
|
||||
return FILERR_INVALID_ACCESS;
|
||||
|
||||
/* if we have been compressing, flush and free the data */
|
||||
if (file->zdata != NULL && !compress)
|
||||
if (file->zdata != NULL && level == FCOMPRESS_NONE)
|
||||
{
|
||||
int zerr = Z_OK;
|
||||
|
||||
@ -278,7 +279,7 @@ file_error core_fcompress(core_file *file, int compress)
|
||||
}
|
||||
|
||||
/* if we are just starting to compress, allocate a new buffer */
|
||||
if (file->zdata == NULL && compress)
|
||||
if (file->zdata == NULL && level > FCOMPRESS_NONE)
|
||||
{
|
||||
int zerr;
|
||||
|
||||
@ -293,7 +294,7 @@ file_error core_fcompress(core_file *file, int compress)
|
||||
{
|
||||
file->zdata->stream.next_out = file->zdata->buffer;
|
||||
file->zdata->stream.avail_out = sizeof(file->zdata->buffer);
|
||||
zerr = deflateInit(&file->zdata->stream, Z_BEST_COMPRESSION);
|
||||
zerr = deflateInit(&file->zdata->stream, level);
|
||||
}
|
||||
else
|
||||
zerr = inflateInit(&file->zdata->stream);
|
||||
|
@ -26,6 +26,11 @@
|
||||
|
||||
#define OPEN_FLAG_NO_BOM 0x0100 /* don't output BOM */
|
||||
|
||||
#define FCOMPRESS_NONE 0 /* no compression */
|
||||
#define FCOMPRESS_MIN 1 /* minimal compression */
|
||||
#define FCOMPRESS_MEDIUM 6 /* standard compression */
|
||||
#define FCOMPRESS_MAX 9 /* maximum compression */
|
||||
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
@ -55,8 +60,8 @@ file_error core_fopen_ram_copy(const void *data, size_t length, UINT32 openflags
|
||||
/* close an open file */
|
||||
void core_fclose(core_file *file);
|
||||
|
||||
/* enable/disable streaming file compression via zlib */
|
||||
file_error core_fcompress(core_file *file, int compress);
|
||||
/* enable/disable streaming file compression via zlib; level is 0 to disable compression, or up to 9 for max compression */
|
||||
file_error core_fcompress(core_file *file, int level);
|
||||
|
||||
|
||||
|
||||
|
@ -1507,7 +1507,7 @@ static READ16_HANDLER( latch_status_r )
|
||||
if (IS_OUTPUT_EMPTY())
|
||||
result |= 0x40;
|
||||
if (dcs.fifo_status_r != NULL && (!transfer.hle_enabled || transfer.state == 0))
|
||||
result |= (*dcs.fifo_status_r)(NULL) & 0x38;
|
||||
result |= (*dcs.fifo_status_r)(dcs.cpu) & 0x38;
|
||||
if (transfer.hle_enabled && transfer.state != 0)
|
||||
result |= 0x08;
|
||||
return result;
|
||||
@ -1517,7 +1517,7 @@ static READ16_HANDLER( latch_status_r )
|
||||
static READ16_HANDLER( fifo_input_r )
|
||||
{
|
||||
if (dcs.fifo_data_r)
|
||||
return (*dcs.fifo_data_r)(NULL);
|
||||
return (*dcs.fifo_data_r)(dcs.cpu);
|
||||
else
|
||||
return 0xffff;
|
||||
}
|
||||
@ -2064,7 +2064,7 @@ void dcs_fifo_notify(int count, int max)
|
||||
if (transfer.state != 5 || transfer.fifo_entries == transfer.writes_left || transfer.fifo_entries >= 256)
|
||||
{
|
||||
for ( ; transfer.fifo_entries; transfer.fifo_entries--)
|
||||
preprocess_write(Machine, (*dcs.fifo_data_r)(NULL));
|
||||
preprocess_write(Machine, (*dcs.fifo_data_r)(dcs.cpu));
|
||||
}
|
||||
}
|
||||
|
||||
@ -2076,7 +2076,7 @@ static TIMER_CALLBACK( transfer_watchdog_callback )
|
||||
if (transfer.fifo_entries && starting_writes_left == transfer.writes_left)
|
||||
{
|
||||
for ( ; transfer.fifo_entries; transfer.fifo_entries--)
|
||||
preprocess_write(machine, (*dcs.fifo_data_r)(NULL));
|
||||
preprocess_write(machine, (*dcs.fifo_data_r)(dcs.cpu));
|
||||
}
|
||||
timer_adjust_oneshot(transfer.watchdog, ATTOTIME_IN_MSEC(1), transfer.writes_left);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user