Removed cpu_scalebyfcount().

Changed input ports to register a frame callback, which is
called immediately after throttling and updating. This is the
proper "sync point" between emulated time and real time. Moved
all analog and digital port processing into a central place
here. Added tracking of time since the previous frame update
and use that as an estimate for the time of the current frame.
This is used to scale analog ports without the use of
cpu_scalebyfcount(). This is not perfect in the case where
frame rates are dynamic (vector games), but works well for
other cases.

Further cleanup of memory header and code.
This commit is contained in:
Aaron Giles 2008-03-12 05:13:03 +00:00
parent 61b009597e
commit d5561a8e75
9 changed files with 615 additions and 649 deletions

View File

@ -9010,7 +9010,7 @@ static void SetSearchRegionDefaultName(SearchRegion * region)
if(region->writeHandler)
{
genf * handler = region->writeHandler->write.handler;
genf * handler = region->writeHandler->write.generic;
FPTR handlerAddress = (FPTR)handler;
if( (handlerAddress >= ((FPTR)SMH_BANK1)) && (handlerAddress <= ((FPTR)SMH_BANK24)))
@ -9159,9 +9159,9 @@ static void BuildSearchRegions(running_machine *machine, SearchInfo * info)
SearchRegion * traverse;
int count = 0;
map = memory_get_map(info->targetIdx, ADDRESS_SPACE_PROGRAM);
map = memory_get_address_map(info->targetIdx, ADDRESS_SPACE_PROGRAM);
for (entry = map->entrylist; entry != NULL; entry = entry->next)
if (entry->write.handler)
if (entry->write.generic)
count++;
info->regionList = calloc(sizeof(SearchRegion), count);
@ -9170,7 +9170,7 @@ static void BuildSearchRegions(running_machine *machine, SearchInfo * info)
for (entry = map->entrylist; entry != NULL; entry = entry->next)
{
if (entry->write.handler)
if (entry->write.generic)
{
UINT32 length = (entry->addrend - entry->addrstart) + 1;
@ -10466,11 +10466,11 @@ static void DoSearch(SearchInfo * search)
static UINT8 ** LookupHandlerMemory(UINT8 cpu, UINT32 address, UINT32 * outRelativeAddress)
{
const address_map * map = memory_get_map(cpu, ADDRESS_SPACE_PROGRAM);
const address_map * map = memory_get_address_map(cpu, ADDRESS_SPACE_PROGRAM);
const address_map_entry *entry;
for (entry = map->entrylist; entry != NULL; entry = entry->next)
if (entry->write.handler != NULL && (address >= entry->addrstart) && (address <= entry->addrend))
if (entry->write.generic != NULL && (address >= entry->addrstart) && (address <= entry->addrend))
{
if(outRelativeAddress)
*outRelativeAddress = address - entry->addrstart;

View File

@ -741,29 +741,6 @@ void cpu_triggerint(running_machine *machine, int cpunum)
CHEESY FAKE VIDEO TIMING
***************************************************************************/
/*-------------------------------------------------
cpu_scalebyfcount - scale by time between
refresh timers
-------------------------------------------------*/
int cpu_scalebyfcount(int value)
{
// attotime refresh_elapsed = timer_timeelapsed(refresh_timer);
// int result;
/* shift off some bits to ensure no overflow */
// if (value < 65536)
// result = value * (refresh_elapsed.attoseconds >> 16) / (refresh_period.attoseconds >> 16);
// else
// result = value * (refresh_elapsed.attoseconds >> 32) / (refresh_period.attoseconds >> 32);
// if (value >= 0)
// return (result < value) ? result : value;
// else
// return (result > value) ? result : value;
return 0;
}
/*-------------------------------------------------
cpu_getiloops - return the cheesy VBLANK
interrupt counter (deprecated)

View File

@ -65,8 +65,5 @@ extern running_machine *Machine;
that the interrupt handler will be called once. */
int cpu_getiloops(void);
/* Scales a given value by the ratio of fcount / fperiod */
int cpu_scalebyfcount(int value);
#endif /* __DEPRECAT_H__ */

View File

@ -265,6 +265,8 @@ static double rec_speed;
static int extended_inp;
/* for average speed calculations */
static attotime last_update;
static attoseconds_t last_delta;
static int framecount;
static double totalspeed;
@ -1032,14 +1034,12 @@ static int default_ports_lookup[__ipt_max][MAX_PLAYERS];
FUNCTION PROTOTYPES
***************************************************************************/
static void on_vblank(running_machine *machine, int vblank_state);
static void setup_playback(running_machine *machine);
static void setup_record(running_machine *machine);
static void input_port_exit(running_machine *machine);
static void input_port_frame(running_machine *machine);
static void input_port_load(int config_type, xml_data_node *parentnode);
static void input_port_save(int config_type, xml_data_node *parentnode);
static void input_port_vblank_start(running_machine *machine);
static void input_port_vblank_end(void);
static void update_digital_joysticks(void);
static void update_analog_port(int port);
static void interpolate_analog_port(int port);
@ -1063,6 +1063,7 @@ void input_port_init(running_machine *machine, const input_port_token *ipt)
/* add an exit callback */
add_exit_callback(machine, input_port_exit);
add_frame_callback(machine, input_port_frame);
/* start with the raw defaults and ask the OSD to customize them in the backup array */
memcpy(default_ports_backup, default_ports_builtin, sizeof(default_ports_backup));
@ -1139,32 +1140,6 @@ void input_port_init(running_machine *machine, const input_port_token *ipt)
}
void input_port_post_init(running_machine *machine)
{
/* set up callback for updating the ports */
video_screen_register_global_vbl_cb(on_vblank);
}
/*************************************
*
* VBLANK handler
*
*************************************/
static void on_vblank(running_machine *machine, int vblank_state)
{
/* VBLANK starting - read keyboard & update the status of the input ports */
if (vblank_state)
input_port_vblank_start(machine);
/* VBLANK ending - update IPT_VBLANK input ports */
else
input_port_vblank_end();
}
/*************************************
*
@ -1539,7 +1514,7 @@ static void input_port_postload(void)
}
/* run an initial update */
input_port_vblank_start(Machine);
input_port_frame(Machine);
}
@ -2799,22 +2774,22 @@ profiler_mark(PROFILER_END);
*
*************************************/
static void update_playback_record(int portnum, UINT32 portvalue)
static void update_playback_record(running_machine *machine, int portnum, UINT32 portvalue)
{
/* handle playback */
if (Machine->playback_file != NULL)
if (machine->playback_file != NULL)
{
UINT32 result;
/* a successful read goes into the playback field which overrides everything else */
if (mame_fread(Machine->playback_file, &result, sizeof(result)) == sizeof(result))
if (mame_fread(machine->playback_file, &result, sizeof(result)) == sizeof(result))
portvalue = port_info[portnum].playback = BIG_ENDIANIZE_INT32(result);
/* a failure causes us to close the playback file and stop playback */
else
{
mame_fclose(Machine->playback_file);
Machine->playback_file = NULL;
mame_fclose(machine->playback_file);
machine->playback_file = NULL;
if (!extended_inp)
popmessage("End of playback");
else
@ -2826,19 +2801,19 @@ static void update_playback_record(int portnum, UINT32 portvalue)
}
/* handle recording */
if (Machine->record_file != NULL)
if (machine->record_file != NULL)
{
UINT32 result = BIG_ENDIANIZE_INT32(portvalue);
/* a successful write just works */
if (mame_fwrite(Machine->record_file, &result, sizeof(result)) == sizeof(result))
if (mame_fwrite(machine->record_file, &result, sizeof(result)) == sizeof(result))
;
/* a failure causes us to close the record file and stop recording */
else
{
mame_fclose(Machine->record_file);
Machine->record_file = NULL;
mame_fclose(machine->record_file);
machine->record_file = NULL;
}
}
}
@ -2884,13 +2859,23 @@ void input_port_update_defaults(void)
*
*************************************/
static void input_port_vblank_start(running_machine *machine)
static void input_port_frame(running_machine *machine)
{
int ui_visible = ui_is_menu_active() || ui_is_slider_active();
attotime curtime = timer_get_time();
int portnum, bitnum;
profiler_mark(PROFILER_INPUT);
/* track the duration of the previous frame */
last_delta = attotime_to_attoseconds(attotime_sub(curtime, last_update)) / ATTOSECONDS_PER_SECOND_SQRT;
last_update = curtime;
/* update all analog ports if the UI isn't visible */
if (!ui_visible)
for (portnum = 0; portnum < MAX_INPUT_PORTS; portnum++)
update_analog_port(portnum);
/* update the digital joysticks first */
update_digital_joysticks();
@ -2958,15 +2943,15 @@ profiler_mark(PROFILER_INPUT);
UINT8 mask;
switch( port->way )
{
case 4:
mask = joyinfo->current4way;
break;
case 16:
mask = 0xff;
break;
default:
mask = joyinfo->current;
break;
case 4:
mask = joyinfo->current4way;
break;
case 16:
mask = 0xff;
break;
default:
mask = joyinfo->current;
break;
}
if ((mask >> JOYSTICK_DIR_FOR_PORT(port)) & 1)
portinfo->digital ^= port->mask;
@ -3025,7 +3010,7 @@ profiler_mark(PROFILER_INPUT);
/* non-analog ports must be manually updated */
else
update_playback_record(portnum, readinputport(portnum));
update_playback_record(machine, portnum, readinputport(portnum));
}
/* store speed read from INP file, if extended INP */
@ -3044,29 +3029,6 @@ profiler_mark(PROFILER_END);
/*************************************
*
* VBLANK end routine
*
*************************************/
static void input_port_vblank_end(void)
{
int ui_visible = ui_is_menu_active() || ui_is_slider_active();
int port;
profiler_mark(PROFILER_INPUT);
/* update all analog ports if the UI isn't visible */
if (!ui_visible)
for (port = 0; port < MAX_INPUT_PORTS; port++)
update_analog_port(port);
profiler_mark(PROFILER_END);
}
/*************************************
*
* Digital joystick updating
@ -3380,8 +3342,11 @@ profiler_mark(PROFILER_INPUT);
INT32 value;
/* interpolate or not */
if (info->interpolate && !port->analog.reset)
current = info->previous + cpu_scalebyfcount(info->accum - info->previous);
if (info->interpolate && !port->analog.reset && last_delta != 0)
{
attoseconds_t time_since_last = attotime_to_attoseconds(attotime_sub(timer_get_time(), last_update)) / ATTOSECONDS_PER_SECOND_SQRT;
current = info->previous + ((INT64)(info->accum - info->previous) * time_since_last / last_delta);
}
else
current = info->accum;
@ -3457,7 +3422,7 @@ UINT32 readinputport(int port)
/* if we have analog data, update the recording state */
if (port_info[port].analoginfo)
update_playback_record(port, result);
update_playback_record(Machine, port, result);
/* if we're playing back, use the recorded value for inputs instead */
if (Machine->playback_file != NULL)

View File

@ -1585,7 +1585,6 @@ static void init_machine(running_machine *machine)
crosshair_init(machine);
sound_init(machine);
input_port_post_init(machine);
#ifdef ENABLE_DEBUGGER
/* initialize the debugger */

View File

@ -167,7 +167,7 @@ typedef enum _read_or_write read_or_write;
MACROS
***************************************************************************/
/* ----- table lookup helpers ----- */
/* table lookup helpers */
#define LEVEL1_INDEX(a) ((a) >> LEVEL2_BITS)
#define LEVEL2_INDEX(e,a) ((1 << LEVEL1_BITS) + (((e) - SUBTABLE_BASE) << LEVEL2_BITS) + ((a) & ((1 << LEVEL2_BITS) - 1)))
@ -236,23 +236,15 @@ struct _bank_data
void * entryd[MAX_BANK_ENTRIES];/* array of decrypted entries for this bank */
};
typedef union _rwhandlers rwhandlers;
union _rwhandlers
{
genf * generic; /* generic handler void */
read_handlers read; /* read handlers */
write_handlers write; /* write handlers */
};
/* In memory.h: typedef struct _handler_data handler_data */
struct _handler_data
{
rwhandlers handler; /* function pointer for handler */
memory_handler handler; /* function pointer for handler */
void * object; /* object associated with the handler */
const char * name; /* name of the handler */
offs_t bytestart; /* byte-adjusted start address for handler */
offs_t byteend; /* byte-adjusted end address for handler */
offs_t bytemask; /* byte-adjusted mask against the final address */
void * object; /* object associated with the handler */
const char * name; /* name of the handler */
};
typedef struct _subtable_data subtable_data;
@ -490,24 +482,23 @@ INLINE void adjust_addresses(addrspace_data *space, offs_t *start, offs_t *end,
void memory_init(running_machine *machine)
{
int i;
int spacenum;
for (i = 0; i < ADDRESS_SPACES; i++)
log_unmap[i] = TRUE;
add_exit_callback(machine, memory_exit);
/* no current context to start */
/* reset globals */
cur_context = -1;
for (spacenum = 0; spacenum < ADDRESS_SPACES; spacenum++)
log_unmap[spacenum] = TRUE;
/* reset the shared pointers and bank pointers */
memset(shared_ptr, 0, sizeof(shared_ptr));
memset(bank_ptr, 0, sizeof(bank_ptr));
memset(bankd_ptr, 0, sizeof(bankd_ptr));
/* init the CPUs */
/* build up the cpudata array with info about all CPUs and address spaces */
memory_init_cpudata(machine->config);
add_exit_callback(machine, memory_exit);
/* preflight the memory handlers and check banks */
memory_init_preflight(machine->config);
@ -639,17 +630,6 @@ const data_accessors *memory_get_accessors(int spacenum, int databits, int endia
}
/*-------------------------------------------------
memory_get_map - return a pointer to a CPU's
memory map
-------------------------------------------------*/
const address_map *memory_get_map(int cpunum, int spacenum)
{
return cpudata[cpunum].space[spacenum].map;
}
/*-------------------------------------------------
memory_set_opbase_handler - change op-code
memory base
@ -1185,7 +1165,7 @@ UINT64 *_memory_install_readwrite64_handler(int cpunum, int spacenum, offs_t add
/*-------------------------------------------------
address_map_alloc - build and allocate an
address map
address map for a CPU's address space
-------------------------------------------------*/
address_map *address_map_alloc(const machine_config *config, int cpunum, int spacenum)
@ -1231,6 +1211,18 @@ void address_map_free(address_map *map)
}
/*-------------------------------------------------
memory_get_address_map - return a pointer to
the constructed address map for a CPU's
address space
-------------------------------------------------*/
const address_map *memory_get_address_map(int cpunum, int spacenum)
{
return cpudata[cpunum].space[spacenum].map;
}
/*-------------------------------------------------
address_map_detokenize - detokenize an array
of address map tokens
@ -1504,7 +1496,7 @@ static void memory_init_preflight(const machine_config *config)
adjust_addresses(space, &entry->bytestart, &entry->byteend, &entry->bytemask, &entry->bytemirror);
/* if this is a ROM handler without a specified region, attach it to the implicit region */
if (spacenum == ADDRESS_SPACE_PROGRAM && HANDLER_IS_ROM(entry->read.handler) && entry->region == 0)
if (spacenum == ADDRESS_SPACE_PROGRAM && HANDLER_IS_ROM(entry->read.generic) && entry->region == 0)
{
/* make sure it fits within the memory region before doing so, however */
if (entry->byteend < cpu->regionsize)
@ -1532,10 +1524,10 @@ static void memory_init_preflight(const machine_config *config)
entry->memory = memory_region(entry->region) + entry->region_offs;
/* assign static banks for explicitly specified entries */
if (HANDLER_IS_BANK(entry->read.handler))
bank_assign_static(HANDLER_TO_BANK(entry->read.handler), cpunum, spacenum, ROW_READ, entry->bytestart, entry->byteend);
if (HANDLER_IS_BANK(entry->write.handler))
bank_assign_static(HANDLER_TO_BANK(entry->write.handler), cpunum, spacenum, ROW_WRITE, entry->bytestart, entry->byteend);
if (HANDLER_IS_BANK(entry->read.generic))
bank_assign_static(HANDLER_TO_BANK(entry->read.generic), cpunum, spacenum, ROW_READ, entry->bytestart, entry->byteend);
if (HANDLER_IS_BANK(entry->write.generic))
bank_assign_static(HANDLER_TO_BANK(entry->write.generic), cpunum, spacenum, ROW_WRITE, entry->bytestart, entry->byteend);
}
/* now loop over all the handlers and enforce the address mask */
@ -1579,7 +1571,7 @@ static void memory_init_populate(running_machine *machine)
for (entry = space->map->entrylist; entry->next != last_entry; entry = entry->next) ;
last_entry = entry;
if (entry->read.handler != NULL)
if (entry->read.generic != NULL)
{
void *object = machine;
if (entry->read_devtype != NULL)
@ -1588,9 +1580,9 @@ static void memory_init_populate(running_machine *machine)
if (object == NULL)
fatalerror("Unidentified object in memory map: type=%s tag=%s\n", devtype_name(entry->read_devtype), entry->read_devtag);
}
install_mem_handler_private(space, ROW_READ, space->dbits, entry->addrstart, entry->addrend, entry->addrmask, entry->addrmirror, entry->read.handler, object, entry->read_name);
install_mem_handler_private(space, ROW_READ, space->dbits, entry->addrstart, entry->addrend, entry->addrmask, entry->addrmirror, entry->read.generic, object, entry->read_name);
}
if (entry->write.handler != NULL)
if (entry->write.generic != NULL)
{
void *object = machine;
if (entry->write_devtype != NULL)
@ -1599,7 +1591,7 @@ static void memory_init_populate(running_machine *machine)
if (object == NULL)
fatalerror("Unidentified object in memory map: type=%s tag=%s\n", devtype_name(entry->write_devtype), entry->write_devtag);
}
install_mem_handler_private(space, ROW_WRITE, space->dbits, entry->addrstart, entry->addrend, entry->addrmask, entry->addrmirror, entry->write.handler, object, entry->write_name);
install_mem_handler_private(space, ROW_WRITE, space->dbits, entry->addrstart, entry->addrend, entry->addrmask, entry->addrmirror, entry->write.generic, object, entry->write_name);
}
}
}
@ -1815,40 +1807,45 @@ static genf *bank_assign_dynamic(int cpunum, int spacenum, read_or_write readorw
static UINT8 get_handler_index(handler_data *table, void *object, genf *handler, const char *handler_name, offs_t bytestart, offs_t byteend, offs_t bytemask)
{
int i;
bytestart &= bytemask;
int entry;
/* all static handlers are hardcoded */
if (HANDLER_IS_STATIC(handler))
{
i = (FPTR)handler;
entry = (FPTR)handler;
/* if it is a bank, copy in the relevant information */
if (HANDLER_IS_BANK(handler))
{
table[i].bytestart = bytestart;
table[i].byteend = byteend;
table[i].bytemask = bytemask;
table[i].name = handler_name;
table[i].object = object;
handler_data *hdata = &table[entry];
hdata->bytestart = bytestart;
hdata->byteend = byteend;
hdata->bytemask = bytemask;
hdata->name = handler_name;
}
return i;
return entry;
}
/* otherwise, we have to search */
for (i = STATIC_COUNT; i < SUBTABLE_BASE; i++)
for (entry = STATIC_COUNT; entry < SUBTABLE_BASE; entry++)
{
if (table[i].handler.generic == NULL)
handler_data *hdata = &table[entry];
/* if we hit a NULL hdata, then we need to allocate this one as a new one */
if (hdata->handler.generic == NULL)
{
table[i].handler.generic = handler;
table[i].bytestart = bytestart;
table[i].byteend = byteend;
table[i].bytemask = bytemask;
table[i].name = handler_name;
table[i].object = object;
return i;
hdata->handler.generic = handler;
hdata->bytestart = bytestart;
hdata->byteend = byteend;
hdata->bytemask = bytemask;
hdata->name = handler_name;
hdata->object = object;
return entry;
}
if (table[i].handler.generic == handler && table[i].bytestart == bytestart && table[i].bytemask == bytemask && table[i].object == object)
return i;
/* if we find a perfect match, return a duplicate entry */
if (hdata->handler.generic == handler && hdata->bytestart == bytestart && hdata->bytemask == bytemask && hdata->object == object)
return entry;
}
return 0;
}
@ -2121,7 +2118,7 @@ static int amentry_needs_backing_store(int cpunum, int spacenum, const address_m
if (entry->baseptr != NULL || entry->baseptroffs_plus1 != 0)
return 1;
handler = (FPTR)entry->write.handler;
handler = (FPTR)entry->write.generic;
if (handler < STATIC_COUNT)
{
if (handler != STATIC_INVALID &&
@ -2131,7 +2128,7 @@ static int amentry_needs_backing_store(int cpunum, int spacenum, const address_m
return 1;
}
handler = (FPTR)entry->read.handler;
handler = (FPTR)entry->read.generic;
if (handler < STATIC_COUNT)
{
if (handler != STATIC_INVALID &&

File diff suppressed because it is too large Load Diff

View File

@ -700,7 +700,7 @@ static int validate_cpu(int drivnum, const machine_config *config, const UINT32
}
/* if this is a program space, auto-assign implicit ROM entries */
if ((FPTR)entry->read.handler == STATIC_ROM && !entry->region)
if ((FPTR)entry->read.generic == STATIC_ROM && !entry->region)
{
entry->region = REGION_CPU1 + cpunum;
entry->region_offs = entry->addrstart;

View File

@ -580,7 +580,7 @@ INLINE void taitoic_drawscanline(
static int has_write_handler(int cpunum, write16_machine_func handler)
{
const address_map *map = memory_get_map(cpunum, ADDRESS_SPACE_PROGRAM);
const address_map *map = memory_get_address_map(cpunum, ADDRESS_SPACE_PROGRAM);
const address_map_entry *entry;
for (entry = map->entrylist; entry != NULL; entry = entry->next)
if (entry->write.mhandler16 == handler)