Moved image devices implementation and related UI functions to emu section from MESS [Miodrag Milanovic]

This commit is contained in:
Miodrag Milanovic 2011-01-05 15:59:06 +00:00
parent 56b43ee687
commit 12a5370d85
36 changed files with 8443 additions and 40 deletions

24
.gitattributes vendored
View File

@ -646,6 +646,30 @@ src/emu/hashfile.c svneol=native#text/plain
src/emu/hashfile.h svneol=native#text/plain src/emu/hashfile.h svneol=native#text/plain
src/emu/image.c svneol=native#text/plain src/emu/image.c svneol=native#text/plain
src/emu/image.h svneol=native#text/plain src/emu/image.h svneol=native#text/plain
src/emu/imagedev/bitbngr.c svneol=native#text/plain
src/emu/imagedev/bitbngr.h svneol=native#text/plain
src/emu/imagedev/cartslot.c svneol=native#text/plain
src/emu/imagedev/cartslot.h svneol=native#text/plain
src/emu/imagedev/cassette.c svneol=native#text/plain
src/emu/imagedev/cassette.h svneol=native#text/plain
src/emu/imagedev/cassimg.c svneol=native#text/plain
src/emu/imagedev/cassimg.h svneol=native#text/plain
src/emu/imagedev/chd_cd.c svneol=native#text/plain
src/emu/imagedev/chd_cd.h svneol=native#text/plain
src/emu/imagedev/flopdrv.c svneol=native#text/plain
src/emu/imagedev/flopdrv.h svneol=native#text/plain
src/emu/imagedev/flopimg.c svneol=native#text/plain
src/emu/imagedev/flopimg.h svneol=native#text/plain
src/emu/imagedev/harddriv.c svneol=native#text/plain
src/emu/imagedev/harddriv.h svneol=native#text/plain
src/emu/imagedev/multcart.c svneol=native#text/plain
src/emu/imagedev/multcart.h svneol=native#text/plain
src/emu/imagedev/printer.c svneol=native#text/plain
src/emu/imagedev/printer.h svneol=native#text/plain
src/emu/imagedev/snapquik.c svneol=native#text/plain
src/emu/imagedev/snapquik.h svneol=native#text/plain
src/emu/imagedev/wavfile.c svneol=native#text/plain
src/emu/imagedev/wavfile.h svneol=native#text/plain
src/emu/info.c svneol=native#text/plain src/emu/info.c svneol=native#text/plain
src/emu/info.h svneol=native#text/plain src/emu/info.h svneol=native#text/plain
src/emu/inptport.c svneol=native#text/plain src/emu/inptport.c svneol=native#text/plain

View File

@ -17,6 +17,7 @@ EMUAUDIO = $(EMUOBJ)/audio
EMUDRIVERS = $(EMUOBJ)/drivers EMUDRIVERS = $(EMUOBJ)/drivers
EMULAYOUT = $(EMUOBJ)/layout EMULAYOUT = $(EMUOBJ)/layout
EMUMACHINE = $(EMUOBJ)/machine EMUMACHINE = $(EMUOBJ)/machine
EMUIMAGEDEV = $(EMUOBJ)/imagedev
EMUVIDEO = $(EMUOBJ)/video EMUVIDEO = $(EMUOBJ)/video
OBJDIRS += \ OBJDIRS += \
@ -28,6 +29,7 @@ OBJDIRS += \
$(EMUOBJ)/drivers \ $(EMUOBJ)/drivers \
$(EMUOBJ)/machine \ $(EMUOBJ)/machine \
$(EMUOBJ)/layout \ $(EMUOBJ)/layout \
$(EMUOBJ)/imagedev \
$(EMUOBJ)/video \ $(EMUOBJ)/video \
OSDSRC = $(SRC)/osd OSDSRC = $(SRC)/osd
@ -235,7 +237,22 @@ EMUVIDEOOBJS = \
$(EMUVIDEO)/vector.o \ $(EMUVIDEO)/vector.o \
$(EMUVIDEO)/voodoo.o \ $(EMUVIDEO)/voodoo.o \
LIBEMUOBJS = $(EMUOBJS) $(EMUSOUNDOBJS) $(EMUAUDIOOBJS) $(EMUDRIVEROBJS) $(EMUMACHINEOBJS) $(EMUVIDEOOBJS) EMUIMAGEDEVOBJS = \
$(EMUIMAGEDEV)/bitbngr.o \
$(EMUIMAGEDEV)/cartslot.o \
$(EMUIMAGEDEV)/cassette.o \
$(EMUIMAGEDEV)/cassimg.o \
$(EMUIMAGEDEV)/chd_cd.o \
$(EMUIMAGEDEV)/flopdrv.o \
$(EMUIMAGEDEV)/flopimg.o \
$(EMUIMAGEDEV)/harddriv.o \
$(EMUIMAGEDEV)/multcart.o \
$(EMUIMAGEDEV)/printer.o \
$(EMUIMAGEDEV)/snapquik.o \
$(EMUIMAGEDEV)/wavfile.o \
LIBEMUOBJS = $(EMUOBJS) $(EMUSOUNDOBJS) $(EMUAUDIOOBJS) $(EMUDRIVEROBJS) $(EMUMACHINEOBJS) $(EMUIMAGEDEVOBJS) $(EMUVIDEOOBJS)
$(LIBEMU): $(LIBEMUOBJS) $(LIBEMU): $(LIBEMUOBJS)

523
src/emu/imagedev/bitbngr.c Normal file
View File

@ -0,0 +1,523 @@
/*********************************************************************
bitbngr.c
TRS style "bitbanger" serial port
*********************************************************************/
#include "emu.h"
#include "bitbngr.h"
/***************************************************************************
TYPE DEFINITIONS
***************************************************************************/
typedef struct _bitbanger_token bitbanger_token;
struct _bitbanger_token
{
emu_timer *bitbanger_output_timer;
emu_timer *bitbanger_input_timer;
int output_value;
int build_count;
int build_byte;
attotime idle_delay;
attotime current_baud;
UINT32 input_buffer_size;
UINT32 input_buffer_cursor;
int mode;
int baud;
int tune;
UINT8 input_buffer[1000];
};
/***************************************************************************
FUNCTION PROTOTYPES
***************************************************************************/
static TIMER_CALLBACK(bitbanger_output_timer);
static TIMER_CALLBACK(bitbanger_input_timer);
/***************************************************************************
INLINE FUNCTIONS
***************************************************************************/
/*-------------------------------------------------
get_token - safely gets the bitbanger data
-------------------------------------------------*/
INLINE bitbanger_token *get_token(device_t *device)
{
assert(device != NULL);
assert(device->type() == BITBANGER);
return (bitbanger_token *) downcast<legacy_device_base *>(device)->token();
}
/*-------------------------------------------------
get_config - safely gets the bitbanger config
-------------------------------------------------*/
INLINE const bitbanger_config *get_config(device_t *device)
{
assert(device != NULL);
assert(device->type() == BITBANGER);
return (const bitbanger_config *) device->baseconfig().static_config();
}
/***************************************************************************
IMPLEMENTATION
***************************************************************************/
/*-------------------------------------------------
native_output - outputs data to a file
-------------------------------------------------*/
static void native_output(device_t *bitbanger, UINT8 data)
{
device_image_interface *image = dynamic_cast<device_image_interface *>(bitbanger);
if (image->exists())
{
image->fwrite(&data, 1);
}
}
/*-------------------------------------------------
native_input - inputs data from a file
-------------------------------------------------*/
static UINT32 native_input(device_t *bitbanger, void *buffer, UINT32 length)
{
device_image_interface *image = dynamic_cast<device_image_interface *>(bitbanger);
if (image->exists())
{
return image->fread(buffer, length);
}
return 0;
}
/*-------------------------------------------------
bitbanger_mode_string
-------------------------------------------------*/
const char *bitbanger_mode_string(device_t *device)
{
bitbanger_token *bi = get_token(device);
static const char *const modes[] = {"Printer", "Modem"};
return(modes[bi->mode]);
}
/*-------------------------------------------------
bitbanger_inc_mode
-------------------------------------------------*/
bool bitbanger_inc_mode(device_t *device, bool test)
{
bitbanger_token *bi = get_token(device);
int adjust_mode = (int)bi->mode + 1;
if( adjust_mode >= BITBANGER_MODE_MAX )
return FALSE;
if( !test)
bi->mode = adjust_mode;
return TRUE;
}
/*-------------------------------------------------
bitbanger_dec_mode
-------------------------------------------------*/
bool bitbanger_dec_mode(device_t *device, bool test)
{
bitbanger_token *bi = get_token(device);
int adjust_mode = bi->mode - 1;
if( adjust_mode < 0 )
return FALSE;
if( !test)
bi->mode = adjust_mode;
return TRUE;
}
/*-------------------------------------------------
bitbanger_tune_string
-------------------------------------------------*/
const char *bitbanger_tune_string(device_t *device)
{
bitbanger_token *bi = get_token(device);
static const char *const tunes[] = {"-2.0%", "-1.75%", "-1.5%", "-1.25%", "-1.0%", "-0.75%", "-0.5", "-0.25%", "\xc2\xb1""0%",
"+0.25%", "+0.5%", "+0.75%", "+1.0%", "+1.25%", "+1.5%", "+1.75%", "+2.0%"};
return(tunes[bi->tune]);
}
/*-------------------------------------------------
bitbanger_tune_value
-------------------------------------------------*/
static float bitbanger_tune_value(device_t *device)
{
bitbanger_token *bi = get_token(device);
static const float tunes[] = {0.97f, 0.9825f, 0.985f, 0.9875f, 0.99f, 0.9925f, 0.995f, 0.9975f, 1.0f,
1.0025f, 1.005f, 1.0075f, 1.01f, 1.0125f, 1.015f, 1.0175f, 1.02f};
return(tunes[bi->tune]);
}
/*-------------------------------------------------
bitbanger_baud_value
-------------------------------------------------*/
static UINT32 bitbanger_baud_value(device_t *device)
{
bitbanger_token *bi = get_token(device);
static const float bauds[] = { 150.0f, 300.0f, 600.0f, 1200.0f, 2400.0f, 4800.0f, 9600.0f,
14400.0f, 28800.0f, 38400.0f, 57600.0f, 115200.0f};
float result = bitbanger_tune_value(device) * bauds[bi->baud];
return (UINT32)result;
}
/*-------------------------------------------------
bitbanger_baud_string
-------------------------------------------------*/
const char *bitbanger_baud_string(device_t *device)
{
bitbanger_token *bi = get_token(device);
static const char *const bauds[] = { "150", "300", "600", "1200", "2400", "4800",
"9600", "14400", "28800", "38400", "57600", "115200"};
return(bauds[bi->baud]);
}
/*-------------------------------------------------
bitbanger_inc_baud
-------------------------------------------------*/
bool bitbanger_inc_baud(device_t *device, bool test)
{
bitbanger_token *bi = get_token(device);
int adjust_baud = (int)bi->baud + 1;
if( adjust_baud >= BITBANGER_BAUD_MAX )
return FALSE;
if( !test)
{
bi->baud = adjust_baud;
bi->current_baud = ATTOTIME_IN_HZ(bitbanger_baud_value(device));
}
return TRUE;
}
/*-------------------------------------------------
bitbanger_dec_baud
-------------------------------------------------*/
bool bitbanger_dec_baud(device_t *device, bool test)
{
bitbanger_token *bi = get_token(device);
int adjust_baud = bi->baud - 1;
if( adjust_baud < 0 )
return FALSE;
if( !test)
{
bi->baud = adjust_baud;
bi->current_baud = ATTOTIME_IN_HZ(bitbanger_baud_value(device));
}
return TRUE;
}
/*-------------------------------------------------
bitbanger_inc_tune
-------------------------------------------------*/
bool bitbanger_inc_tune(device_t *device, bool test)
{
bitbanger_token *bi = get_token(device);
int adjust_tune = (int)bi->tune + 1;
if( adjust_tune >= BITBANGER_TUNE_MAX )
return FALSE;
if( !test)
{
bi->tune = adjust_tune;
bi->current_baud = ATTOTIME_IN_HZ(bitbanger_baud_value(device));
}
return TRUE;
}
/*-------------------------------------------------
bitbanger_dec_tune
-------------------------------------------------*/
bool bitbanger_dec_tune(device_t *device, bool test)
{
bitbanger_token *bi = get_token(device);
int adjust_tune = bi->tune - 1;
if( adjust_tune < 0 )
return FALSE;
if( !test)
{
bi->tune = adjust_tune;
bi->current_baud = ATTOTIME_IN_HZ(bitbanger_baud_value(device));
}
return TRUE;
}
/*-------------------------------------------------
bitbanger_bytes_to_bits_81N
-------------------------------------------------*/
static void bitbanger_bytes_to_bits_81N(device_t *img)
{
bitbanger_token *bi = get_token(img);
UINT8 byte_buffer[100];
UINT32 byte_buffer_size, bit_buffer_size;
int i, j;
static const UINT8 bitmask[8] = {0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80 };
bit_buffer_size = 0;
byte_buffer_size = native_input(img, byte_buffer, sizeof(byte_buffer));
/* Translate byte buffer into bit buffer using: 1 start bit, 8 data bits, 1 stop bit, no parity */
for( i=0; i<byte_buffer_size; i++ )
{
bi->input_buffer[bit_buffer_size++] = 0;
for( j=0; j<8; j++ )
{
if( byte_buffer[i] & bitmask[j] )
bi->input_buffer[bit_buffer_size++] = 1;
else
bi->input_buffer[bit_buffer_size++] = 0;
}
bi->input_buffer[bit_buffer_size++] = 1;
}
bi->input_buffer_size = bit_buffer_size;
bi->input_buffer_cursor = 0;
}
/*-------------------------------------------------
DEVICE_START(bitbanger)
-------------------------------------------------*/
static DEVICE_START(bitbanger)
{
bitbanger_token *bi;
const bitbanger_config *config = get_config(device);
bi = get_token(device);
/* output config */
bi->build_count = 0;
bi->bitbanger_output_timer = timer_alloc(device->machine, bitbanger_output_timer, (void *) device);
/* input config */
bi->bitbanger_input_timer = timer_alloc(device->machine, bitbanger_input_timer, (void *) device );
bi->idle_delay = ATTOTIME_IN_SEC(1);
bi->input_buffer_size = 0;
bi->input_buffer_cursor = 0;
bi->mode = config->default_mode;
bi->baud = config->default_baud;
bi->tune = config->default_tune;
bi->current_baud = ATTOTIME_IN_HZ(bitbanger_baud_value(device));
/* test callback */
if(!config->input_callback)
fatalerror("Misconfigured bitbanger device: input_callback cannot be NULL\n");
}
/*-------------------------------------------------
TIMER_CALLBACK(bitbanger_output_timer)
-------------------------------------------------*/
static TIMER_CALLBACK(bitbanger_output_timer)
{
device_t *device = (device_t *) ptr;
bitbanger_token *bi = get_token(device);
/* this ia harded coded for 8-1-N */
if( bi->output_value )
bi->build_byte |= 0x200;
bi->build_byte >>= 1;
bi->build_count--;
if(bi->build_count == 0)
{
if( bi->output_value == 1 )
native_output( device, bi->build_byte );
else
logerror("Bitbanger: Output framing error.\n" );
timer_reset(bi->bitbanger_output_timer, attotime_never);
}
}
/*-------------------------------------------------
TIMER_CALLBACK(bitbanger_input_timer)
-------------------------------------------------*/
static TIMER_CALLBACK(bitbanger_input_timer)
{
device_t *device = (device_t *) ptr;
bitbanger_token *bi = get_token(device);
const bitbanger_config *config = get_config(device);
if(bi->input_buffer_cursor == bi->input_buffer_size)
{
/* get more data */
bitbanger_bytes_to_bits_81N(device);
if(bi->input_buffer_size == 0)
{
/* no more data, wait and try again */
bi->idle_delay = attotime_min(attotime_add(bi->idle_delay, ATTOTIME_IN_MSEC(100)), ATTOTIME_IN_SEC(1));
timer_adjust_oneshot(bi->bitbanger_input_timer, bi->idle_delay, 0);
if( bi->mode == BITBANGER_MODEM )
config->input_callback(machine, 1);
else
config->input_callback(machine, 0);
return;
}
else
{
bi->idle_delay = bi->current_baud;
timer_adjust_periodic(bi->bitbanger_input_timer, bi->idle_delay, 0, bi->idle_delay);
}
}
/* send bit to driver */
config->input_callback(machine, bi->input_buffer[(bi->input_buffer_cursor)++]);
}
/*-------------------------------------------------
bitbanger_output - outputs data to a bitbanger
port
-------------------------------------------------*/
void bitbanger_output(device_t *device, int value)
{
bitbanger_token *bi = get_token(device);
attotime one_point_five_baud;
if( bi->build_count == 0 && bi->output_value == 1 && value == 0 )
{
/* we found our start bit */
/* eight bits of data, plus one of stop */
bi->build_count = 9;
bi->build_byte = 0;
one_point_five_baud = attotime_add(bi->current_baud, attotime_div(bi->current_baud,2));
timer_adjust_periodic(bi->bitbanger_output_timer, one_point_five_baud, 0, bi->current_baud);
}
//fprintf(stderr,"%s, %d\n", attotime_string(timer_get_time(device->machine),9), value);
bi->output_value = value;
}
/*-------------------------------------------------
DEVICE_IMAGE_LOAD( bitbanger )
-------------------------------------------------*/
static DEVICE_IMAGE_LOAD( bitbanger )
{
device_t *device = &image.device();
bitbanger_token *bi;
bi = get_token(device);
timer_enable(bi->bitbanger_input_timer, TRUE);
timer_adjust_periodic(bi->bitbanger_input_timer, attotime_zero, 0, ATTOTIME_IN_SEC(1));
/* we don't need to do anything special */
return IMAGE_INIT_PASS;
}
/*-------------------------------------------------
DEVICE_IMAGE_UNLOAD( bitbanger )
-------------------------------------------------*/
static DEVICE_IMAGE_UNLOAD( bitbanger )
{
device_t *device = &image.device();
bitbanger_token *bi;
bi = get_token(device);
timer_enable(bi->bitbanger_input_timer, FALSE);
}
/*-------------------------------------------------
DEVICE_GET_INFO(bitbanger) - device getinfo
function
-------------------------------------------------*/
DEVICE_GET_INFO(bitbanger)
{
switch(state)
{
/* --- the following bits of info are returned as 64-bit signed integers --- */
case DEVINFO_INT_TOKEN_BYTES: info->i = sizeof(bitbanger_token); break;
case DEVINFO_INT_INLINE_CONFIG_BYTES: info->i = 0; break;
case DEVINFO_INT_IMAGE_TYPE: info->i = IO_PRINTER; break;
case DEVINFO_INT_IMAGE_READABLE: info->i = 1; break;
case DEVINFO_INT_IMAGE_WRITEABLE: info->i = 1; break;
case DEVINFO_INT_IMAGE_CREATABLE: info->i = 1; break;
/* --- the following bits of info are returned as pointers to data or functions --- */
case DEVINFO_FCT_START: info->start = DEVICE_START_NAME(bitbanger); break;
case DEVINFO_FCT_IMAGE_LOAD: info->f = (genf *) DEVICE_IMAGE_LOAD_NAME(bitbanger); break;
case DEVINFO_FCT_IMAGE_UNLOAD: info->f = (genf *) DEVICE_IMAGE_UNLOAD_NAME(bitbanger); break;
/* --- the following bits of info are returned as NULL-terminated strings --- */
case DEVINFO_STR_NAME: strcpy(info->s, "Bitbanger"); break;
case DEVINFO_STR_FAMILY: strcpy(info->s, "Bitbanger"); break;
case DEVINFO_STR_SOURCE_FILE: strcpy(info->s, __FILE__); break;
case DEVINFO_STR_IMAGE_FILE_EXTENSIONS: strcpy(info->s, "prn"); break;
}
}
DEFINE_LEGACY_IMAGE_DEVICE(BITBANGER, bitbanger);

View File

@ -0,0 +1,99 @@
/*********************************************************************
bitbngr.h
TRS style "bitbanger" serial port
*********************************************************************/
#ifndef __BITBNGR_H__
#define __BITBNGR_H__
#include "image.h"
enum
{
BITBANGER_PRINTER = 0,
BITBANGER_MODEM,
BITBANGER_MODE_MAX,
BITBANGER_150 = 0,
BITBANGER_300,
BITBANGER_600,
BITBANGER_1200,
BITBANGER_2400,
BITBANGER_4800,
BITBANGER_9600,
BITBANGER_14400,
BITBANGER_28800,
BITBANGER_38400,
BITBANGER_57600,
BITBANGER_115200,
BITBANGER_BAUD_MAX,
BITBANGER_NEG40PERCENT = 0,
BITBANGER_NEG35PERCENT,
BITBANGER_NEG30PERCENT,
BITBANGER_NEG25PERCENT,
BITBANGER_NEG20PERCENT,
BITBANGER_NEG15PERCENT,
BITBANGER_NEG10PERCENT,
BITBANGER_NEG5PERCENT,
BITBANGER_0PERCENT,
BITBANGER_POS5PERCENT,
BITBANGER_POS10PERCENT,
BITBANGER_POS15PERCENT,
BITBANGER_POS20PERCENT,
BITBANGER_POS25PERCENT,
BITBANGER_POS30PERCENT,
BITBANGER_POS35PERCENT,
BITBANGER_POS40PERCENT,
BITBANGER_TUNE_MAX
};
/***************************************************************************
CONSTANTS
***************************************************************************/
DECLARE_LEGACY_IMAGE_DEVICE(BITBANGER, bitbanger);
#define MCFG_BITBANGER_ADD(_tag, _intrf) \
MCFG_DEVICE_ADD(_tag, BITBANGER, 0) \
MCFG_DEVICE_CONFIG(_intrf)
/***************************************************************************
TYPE DEFINITIONS
***************************************************************************/
typedef struct _bitbanger_config bitbanger_config;
struct _bitbanger_config
{
/* callback to driver */
void (*input_callback)(running_machine *machine, UINT8 bit);
int default_mode; /* emulating a printer or modem */
int default_baud; /* output bits per second */
int default_tune; /* fine tune adjustment to the baud */
};
/***************************************************************************
FUNCTION PROTOTYPES
***************************************************************************/
/* outputs data to a bitbanger port */
void bitbanger_output(device_t *device, int value);
/* ui functions */
const char *bitbanger_mode_string(device_t *device);
const char *bitbanger_baud_string(device_t *device);
const char *bitbanger_tune_string(device_t *device);
bool bitbanger_inc_mode(device_t *device, bool test);
bool bitbanger_dec_mode(device_t *device, bool test);
bool bitbanger_inc_tune(device_t *device, bool test);
bool bitbanger_dec_tune(device_t *device, bool test);
bool bitbanger_inc_baud(device_t *device, bool test);
bool bitbanger_dec_baud(device_t *device, bool test);
#endif /* __BITBNGR_H__ */

569
src/emu/imagedev/cartslot.c Normal file
View File

@ -0,0 +1,569 @@
/**********************************************************************
cartslot.c
Cartridge device
**********************************************************************/
#include <ctype.h>
#include "emu.h"
#include "cartslot.h"
#include "multcart.h"
/***************************************************************************
CONSTANTS
***************************************************************************/
enum _process_mode
{
PROCESS_CLEAR,
PROCESS_LOAD
};
typedef enum _process_mode process_mode;
/***************************************************************************
INLINE FUNCTIONS
***************************************************************************/
INLINE cartslot_t *get_token(device_t *device)
{
assert(device != NULL);
assert(device->type() == CARTSLOT);
return (cartslot_t *) downcast<legacy_device_base *>(device)->token();
}
INLINE const cartslot_config *get_config(device_t *device)
{
assert(device != NULL);
assert(device->type() == CARTSLOT);
return (const cartslot_config *) downcast<const legacy_device_config_base &>(device->baseconfig()).inline_config();
}
INLINE const cartslot_config *get_config_dev(const device_config *device)
{
assert(device != NULL);
assert(device->type() == CARTSLOT);
return (const cartslot_config *)downcast<const legacy_device_config_base *>(device)->inline_config();
}
/***************************************************************************
IMPLEMENTATION
***************************************************************************/
/*-------------------------------------------------
load_cartridge
-------------------------------------------------*/
static int load_cartridge(device_image_interface *image, const rom_entry *romrgn, const rom_entry *roment, process_mode mode)
{
const char *region;
const char *type;
UINT32 flags;
offs_t offset, length, read_length, pos = 0, len;
UINT8 *ptr;
UINT8 clear_val;
int datawidth, littleendian, i, j;
device_t *cpu;
region = ROMREGION_GETTAG(romrgn);
offset = ROM_GETOFFSET(roment);
length = ROM_GETLENGTH(roment);
flags = ROM_GETFLAGS(roment);
ptr = ((UINT8 *) image->device().machine->region(region)->base()) + offset;
if (mode == PROCESS_LOAD)
{
if (image->software_entry() == NULL)
{
/* must this be full size */
if (flags & ROM_FULLSIZE)
{
if (image->length() != length)
return IMAGE_INIT_FAIL;
}
/* read the ROM */
pos = read_length = image->fread(ptr, length);
/* reset the ROM to the initial point. */
/* eventually, we could add a flag to allow the ROM to continue instead of restarting whenever a new cart region is present */
image->fseek(0, SEEK_SET);
}
else
{
/* must this be full size */
if (flags & ROM_FULLSIZE)
{
if (image->get_software_region_length("rom") != length)
return IMAGE_INIT_FAIL;
}
/* read the ROM */
pos = read_length = image->get_software_region_length("rom");
memcpy(ptr, image->get_software_region("rom"), read_length);
}
/* do we need to mirror the ROM? */
if (flags & ROM_MIRROR)
{
while(pos < length)
{
len = MIN(read_length, length - pos);
memcpy(ptr + pos, ptr, len);
pos += len;
}
}
/* postprocess this region */
type = ROMREGION_GETTAG(romrgn);
littleendian = ROMREGION_ISLITTLEENDIAN(romrgn);
datawidth = ROMREGION_GETWIDTH(romrgn) / 8;
/* if the region is inverted, do that now */
device_memory_interface *memory;
cpu = image->device().machine->device(type);
if (cpu!=NULL && cpu->interface(memory))
{
datawidth = device_memory(cpu)->space_config(AS_PROGRAM)->m_databus_width / 8;
littleendian = (device_memory(cpu)->space_config()->m_endianness == ENDIANNESS_LITTLE);
}
/* swap the endianness if we need to */
#ifdef LSB_FIRST
if (datawidth > 1 && !littleendian)
#else
if (datawidth > 1 && littleendian)
#endif
{
for (i = 0; i < length; i += datawidth)
{
UINT8 temp[8];
memcpy(temp, &ptr[i], datawidth);
for (j = datawidth - 1; j >= 0; j--)
ptr[i + j] = temp[datawidth - 1 - j];
}
}
}
/* clear out anything that remains */
if (!(flags & ROM_NOCLEAR))
{
clear_val = (flags & ROM_FILL_FF) ? 0xFF : 0x00;
memset(ptr + pos, clear_val, length - pos);
}
return IMAGE_INIT_PASS;
}
/*-------------------------------------------------
process_cartridge
-------------------------------------------------*/
static int process_cartridge(device_image_interface *image, process_mode mode)
{
const rom_source *source;
const rom_entry *romrgn, *roment;
int result = 0;
for (source = rom_first_source(*image->device().machine->config); source != NULL; source = rom_next_source(*source))
{
for (romrgn = rom_first_region(*source); romrgn != NULL; romrgn = rom_next_region(romrgn))
{
roment = romrgn + 1;
while(!ROMENTRY_ISREGIONEND(roment))
{
if (ROMENTRY_GETTYPE(roment) == ROMENTRYTYPE_CARTRIDGE)
{
if (strcmp(roment->_hashdata,image->device().tag())==0)
{
result |= load_cartridge(image, romrgn, roment, mode);
/* if loading failed in any cart region, stop loading */
if (result)
return result;
}
}
roment++;
}
}
}
return IMAGE_INIT_PASS;
}
/*-------------------------------------------------
cartslot_get_pcb
-------------------------------------------------*/
device_t *cartslot_get_pcb(device_t *device)
{
cartslot_t *cart = get_token(device);
return cart->pcb_device;
}
/*-------------------------------------------------
cartslot_get_socket
-------------------------------------------------*/
void *cartslot_get_socket(device_t *device, const char *socket_name)
{
cartslot_t *cart = get_token(device);
device_image_interface *image = dynamic_cast<device_image_interface *>(device);
void *result = NULL;
if (cart->mc != NULL)
{
const multicart_socket *socket;
for (socket = cart->mc->sockets; socket != NULL; socket = socket->next)
{
if (!strcmp(socket->id, socket_name))
break;
}
result = socket ? socket->ptr : NULL;
}
else if (socket_name[0] == '\0')
{
result = image->ptr();
}
return result;
}
/*-------------------------------------------------
cartslot_get_resource_length
-------------------------------------------------*/
int cartslot_get_resource_length(device_t *device, const char *socket_name)
{
cartslot_t *cart = get_token(device);
int result = 0;
if (cart->mc != NULL)
{
const multicart_socket *socket;
for (socket = cart->mc->sockets; socket != NULL; socket = socket->next)
{
if (!strcmp(socket->id, socket_name)) {
break;
}
}
if (socket != NULL)
result = socket->resource->length;
}
else
result = 0;
return result;
}
/*-------------------------------------------------
DEVICE_START( cartslot )
-------------------------------------------------*/
static DEVICE_START( cartslot )
{
cartslot_t *cart = get_token(device);
const cartslot_config *config = get_config(device);
/* if this cartridge has a custom DEVICE_START, use it */
if (config->device_start != NULL)
{
(*config->device_start)(device);
goto done;
}
/* find the PCB (if there is one) */
cart->pcb_device = device->subdevice(TAG_PCB);
done:
return;
}
/*-------------------------------------------------
DEVICE_IMAGE_LOAD( cartslot )
-------------------------------------------------*/
static DEVICE_IMAGE_LOAD( cartslot )
{
int result;
device_t *device = &image.device();
cartslot_t *cart = get_token(device);
const cartslot_config *config = get_config(device);
/* if this cartridge has a custom DEVICE_IMAGE_LOAD, use it */
if (config->device_load != NULL)
return (*config->device_load)(image);
/* try opening this as if it were a multicart */
multicart_open(image.filename(), device->machine->gamedrv->name, MULTICART_FLAGS_LOAD_RESOURCES, &cart->mc);
if (cart->mc == NULL)
{
/* otherwise try the normal route */
result = process_cartridge(&image, PROCESS_LOAD);
if (result != IMAGE_INIT_PASS)
return result;
}
return IMAGE_INIT_PASS;
}
/*-------------------------------------------------
DEVICE_IMAGE_UNLOAD( cartslot )
-------------------------------------------------*/
static DEVICE_IMAGE_UNLOAD( cartslot )
{
device_t *device = &image.device();
cartslot_t *cart = get_token(device);
const cartslot_config *config = get_config(device);
/* if this cartridge has a custom DEVICE_IMAGE_UNLOAD, use it */
if (config->device_unload != NULL)
{
(*config->device_unload)(image);
return;
}
if (cart->mc != NULL)
{
multicart_close(cart->mc);
cart->mc = NULL;
}
process_cartridge(&image, PROCESS_CLEAR);
}
/*-------------------------------------------------
identify_pcb
-------------------------------------------------*/
static const cartslot_pcb_type *identify_pcb(device_image_interface &image)
{
const cartslot_config *config = get_config(&image.device());
astring pcb_name;
const cartslot_pcb_type *pcb_type = NULL;
multicart_t *mc;
int i;
if (image.software_entry() == NULL && image.exists())
{
/* try opening this as if it were a multicart */
multicart_open_error me = multicart_open(image.filename(), image.device().machine->gamedrv->name, MULTICART_FLAGS_DONT_LOAD_RESOURCES, &mc);
if (me == MCERR_NONE)
{
/* this was a multicart - read from it */
astring_cpyc(&pcb_name, mc->pcb_type);
multicart_close(mc);
}
else
{
if (me != MCERR_NOT_MULTICART)
fatalerror("multicart error: %s", multicart_error_text(me));
/* Force fetching of image metadata */
image.crc();
if (image.pcb() != NULL)
{
/* read from hash file */
astring_cpyc(&pcb_name, image.pcb());
}
}
/* look for PCB type with matching name */
for (i = 0; (i < ARRAY_LENGTH(config->pcb_types)) && (config->pcb_types[i].name != NULL); i++)
{
if ((config->pcb_types[i].name[0] == '\0') || !strcmp(astring_c(&pcb_name), config->pcb_types[i].name))
{
pcb_type = &config->pcb_types[i];
break;
}
}
/* check for unknown PCB type */
if ((mc != NULL) && (pcb_type == NULL))
fatalerror("Unknown PCB type \"%s\"", astring_c(&pcb_name));
}
else
{
/* no device loaded; use the default */
pcb_type = (config->pcb_types[0].name != NULL) ? &config->pcb_types[0] : NULL;
}
return pcb_type;
}
/*-------------------------------------------------
DEVICE_IMAGE_GET_DEVICES(cartslot)
-------------------------------------------------*/
static DEVICE_IMAGE_GET_DEVICES(cartslot)
{
const cartslot_pcb_type *pcb_type;
device_t *device = &image.device();
pcb_type = identify_pcb(image);
if (pcb_type != NULL)
{
image_add_device_with_subdevices(device,pcb_type->devtype,TAG_PCB,0);
}
}
/*-------------------------------------------------
DEVICE_IMAGE_SOFTLIST_LOAD(cartslot)
-------------------------------------------------*/
static DEVICE_IMAGE_SOFTLIST_LOAD(cartslot)
{
load_software_part_region( &image.device(), swlist, swname, start_entry );
return TRUE;
}
/*-------------------------------------------------
DEVICE_GET_INFO( cartslot )
-------------------------------------------------*/
DEVICE_GET_INFO( cartslot )
{
switch(state)
{
/* --- the following bits of info are returned as 64-bit signed integers --- */
case DEVINFO_INT_TOKEN_BYTES: info->i = sizeof(cartslot_t); break;
case DEVINFO_INT_INLINE_CONFIG_BYTES: info->i = sizeof(cartslot_config); break;
case DEVINFO_INT_IMAGE_TYPE: info->i = IO_CARTSLOT; break;
case DEVINFO_INT_IMAGE_READABLE: info->i = 1; break;
case DEVINFO_INT_IMAGE_WRITEABLE: info->i = 0; break;
case DEVINFO_INT_IMAGE_CREATABLE: info->i = 0; break;
case DEVINFO_INT_IMAGE_RESET_ON_LOAD: info->i = 1; break;
case DEVINFO_INT_IMAGE_MUST_BE_LOADED:
if ( device && downcast<const legacy_image_device_config_base *>(device)->inline_config()) {
info->i = get_config_dev(device)->must_be_loaded;
} else {
info->i = 0;
}
break;
/* --- the following bits of info are returned as pointers to functions --- */
case DEVINFO_FCT_START: info->start = DEVICE_START_NAME(cartslot); break;
case DEVINFO_FCT_IMAGE_LOAD: info->f = (genf *) DEVICE_IMAGE_LOAD_NAME(cartslot); break;
case DEVINFO_FCT_IMAGE_UNLOAD: info->f = (genf *) DEVICE_IMAGE_UNLOAD_NAME(cartslot); break;
case DEVINFO_FCT_IMAGE_GET_DEVICES: info->f = (genf *) DEVICE_IMAGE_GET_DEVICES_NAME(cartslot); break;
case DEVINFO_FCT_IMAGE_SOFTLIST_LOAD: info->f = (genf *) DEVICE_IMAGE_SOFTLIST_LOAD_NAME(cartslot); break;
case DEVINFO_FCT_IMAGE_PARTIAL_HASH:
if ( device && downcast<const legacy_image_device_config_base *>(device)->inline_config() && get_config_dev(device)->device_partialhash) {
info->f = (genf *) get_config_dev(device)->device_partialhash;
} else {
info->f = NULL;
}
break;
/* --- the following bits of info are returned as NULL-terminated strings --- */
case DEVINFO_STR_NAME: strcpy(info->s, "Cartslot"); break;
case DEVINFO_STR_FAMILY: strcpy(info->s, "Cartslot"); break;
case DEVINFO_STR_SOURCE_FILE: strcpy(info->s, __FILE__); break;
case DEVINFO_STR_IMAGE_FILE_EXTENSIONS:
if ( device && downcast<const legacy_image_device_config_base *>(device)->inline_config() && get_config_dev(device)->extensions )
{
strcpy(info->s, get_config_dev(device)->extensions);
}
else
{
strcpy(info->s, "bin");
}
break;
case DEVINFO_STR_IMAGE_INTERFACE:
if ( device && downcast<const legacy_image_device_config_base *>(device)->inline_config() && get_config_dev(device)->interface )
{
strcpy(info->s, get_config_dev(device)->interface );
}
break;
}
}
DEFINE_LEGACY_IMAGE_DEVICE(CARTSLOT, cartslot);
//**************************************************************************
// DEVICE CONFIG CARTSLOT INTERFACE
//**************************************************************************
//-------------------------------------------------
// device_config_cart_slot_interface - constructor
//-------------------------------------------------
device_config_cart_slot_interface::device_config_cart_slot_interface(const machine_config &mconfig, device_config &devconfig)
: device_config_interface(mconfig, devconfig)
{
}
//-------------------------------------------------
// ~device_config_cart_slot_interface - destructor
//-------------------------------------------------
device_config_cart_slot_interface::~device_config_cart_slot_interface()
{
}
//**************************************************************************
// DEVICE CARTSLOT INTERFACE
//**************************************************************************
//-------------------------------------------------
// device_cart_slot_interface - constructor
//-------------------------------------------------
device_cart_slot_interface::device_cart_slot_interface(running_machine &machine, const device_config &config, device_t &device)
: device_interface(machine, config, device),
m_cart_slot_config(dynamic_cast<const device_config_cart_slot_interface &>(config))
{
}
//-------------------------------------------------
// ~device_cart_slot_interface - destructor
//-------------------------------------------------
device_cart_slot_interface::~device_cart_slot_interface()
{
}
//**************************************************************************
// LEGACY cart_slot DEVICE CONFIGURATION
//**************************************************************************
//-------------------------------------------------
// legacy_cart_slot_device_config_base - constructor
//-------------------------------------------------
legacy_cart_slot_device_config_base::legacy_cart_slot_device_config_base(const machine_config &mconfig, device_type type, const char *tag, const device_config *owner, UINT32 clock, device_get_config_func get_config)
: legacy_device_config_base(mconfig, type, tag, owner, clock, get_config),
device_config_cart_slot_interface(mconfig, *this)
{
}
//**************************************************************************
// LIVE LEGACY cart_slot DEVICE
//**************************************************************************
//-------------------------------------------------
// legacy_cart_slot_device_base - constructor
//-------------------------------------------------
legacy_cart_slot_device_base::legacy_cart_slot_device_base(running_machine &machine, const device_config &config)
: legacy_device_base(machine, config),
device_cart_slot_interface(machine, config, *this)
{
}

180
src/emu/imagedev/cartslot.h Normal file
View File

@ -0,0 +1,180 @@
/***************************************************************************
Cartrige loading
***************************************************************************/
#ifndef __CARTSLOT_H__
#define __CARTSLOT_H__
#include "image.h"
#include "multcart.h"
/***************************************************************************
MACROS
***************************************************************************/
#define TAG_PCB "pcb"
#define ROM_CART_LOAD(tag,offset,length,flags) \
{ NULL, tag, offset, length, ROMENTRYTYPE_CARTRIDGE | (flags) },
#define ROM_MIRROR 0x01000000
#define ROM_NOMIRROR 0x00000000
#define ROM_FULLSIZE 0x02000000
#define ROM_FILL_FF 0x04000000
#define ROM_NOCLEAR 0x08000000
DECLARE_LEGACY_IMAGE_DEVICE(CARTSLOT, cartslot);
/***************************************************************************
TYPE DEFINITIONS
***************************************************************************/
typedef struct _cartslot_t cartslot_t;
struct _cartslot_t
{
device_t *pcb_device;
multicart_t *mc;
};
typedef struct _cartslot_pcb_type cartslot_pcb_type;
struct _cartslot_pcb_type
{
const char * name;
device_type devtype;
};
typedef struct _cartslot_config cartslot_config;
struct _cartslot_config
{
const char * extensions;
const char * interface;
int must_be_loaded;
device_start_func device_start;
device_image_load_func device_load;
device_image_unload_func device_unload;
device_image_partialhash_func device_partialhash;
cartslot_pcb_type pcb_types[16];
};
/***************************************************************************
FUNCTION PROTOTYPES
***************************************************************************/
/* accesses the PCB associated with this cartslot */
device_t *cartslot_get_pcb(device_t *device);
/* accesses a particular socket */
void *cartslot_get_socket(device_t *device, const char *socket_name);
/* accesses a particular socket; gets the length of the associated resource */
int cartslot_get_resource_length(device_t *device, const char *socket_name);
/***************************************************************************
DEVICE CONFIGURATION MACROS
***************************************************************************/
#define MCFG_CARTSLOT_ADD(_tag) \
MCFG_DEVICE_ADD(_tag, CARTSLOT, 0) \
#define MCFG_CARTSLOT_MODIFY(_tag) \
MCFG_DEVICE_MODIFY(_tag) \
#define MCFG_CARTSLOT_EXTENSION_LIST(_extensions) \
MCFG_DEVICE_CONFIG_DATAPTR(cartslot_config, extensions, _extensions)
#define MCFG_CARTSLOT_NOT_MANDATORY \
MCFG_DEVICE_CONFIG_DATA32(cartslot_config, must_be_loaded, FALSE)
#define MCFG_CARTSLOT_MANDATORY \
MCFG_DEVICE_CONFIG_DATA32(cartslot_config, must_be_loaded, TRUE)
#define MCFG_CARTSLOT_START(_start) \
MCFG_DEVICE_CONFIG_DATAPTR(cartslot_config, device_start, DEVICE_START_NAME(_start))
#define MCFG_CARTSLOT_LOAD(_load) \
MCFG_DEVICE_CONFIG_DATAPTR(cartslot_config, device_load, DEVICE_IMAGE_LOAD_NAME(_load))
#define MCFG_CARTSLOT_UNLOAD(_unload) \
MCFG_DEVICE_CONFIG_DATAPTR(cartslot_config, device_unload, DEVICE_IMAGE_UNLOAD_NAME(_unload))
#define MCFG_CARTSLOT_PARTIALHASH(_partialhash) \
MCFG_DEVICE_CONFIG_DATAPTR(cartslot_config, device_partialhash, _partialhash)
#define MCFG_CARTSLOT_PCBTYPE(_index, _pcb_type_name, _pcb_devtype) \
MCFG_DEVICE_CONFIG_DATAPTR_ARRAY_MEMBER(cartslot_config, pcb_types, _index, cartslot_pcb_type, name, _pcb_type_name) \
MCFG_DEVICE_CONFIG_DATAPTR_ARRAY_MEMBER(cartslot_config, pcb_types, _index, cartslot_pcb_type, devtype, _pcb_devtype)
#define MCFG_CARTSLOT_INTERFACE(_interface) \
MCFG_DEVICE_CONFIG_DATAPTR(cartslot_config, interface, _interface )
#define DECLARE_LEGACY_CART_SLOT_DEVICE(name, basename) _DECLARE_LEGACY_DEVICE(name, basename, basename##_device_config, basename##_device, legacy_cart_slot_device_config_base, legacy_cart_slot_device_base)
#define DEFINE_LEGACY_CART_SLOT_DEVICE(name, basename) _DEFINE_LEGACY_DEVICE(name, basename, basename##_device_config, basename##_device, legacy_cart_slot_device_config_base, legacy_cart_slot_device_base)
// ======================> device_config_cart_slot_interface
// class representing interface-specific configuration cart_slot
class device_config_cart_slot_interface : public device_config_interface
{
public:
// construction/destruction
device_config_cart_slot_interface(const machine_config &mconfig, device_config &device);
virtual ~device_config_cart_slot_interface();
};
// ======================> device_cart_slot_interface
// class representing interface-specific live cart_slot
class device_cart_slot_interface : public device_interface
{
public:
// construction/destruction
device_cart_slot_interface(running_machine &machine, const device_config &config, device_t &device);
virtual ~device_cart_slot_interface();
// configuration access
const device_config_cart_slot_interface &cart_slot_config() const { return m_cart_slot_config; }
protected:
// configuration
const device_config_cart_slot_interface &m_cart_slot_config; // reference to our device_config_execute_interface
};
// ======================> legacy_cart_slot_device_config
// legacy_cart_slot_device_config is a device_config with a cart_slot interface
class legacy_cart_slot_device_config_base : public legacy_device_config_base,
public device_config_cart_slot_interface
{
protected:
// construction/destruction
legacy_cart_slot_device_config_base(const machine_config &mconfig, device_type type, const char *tag, const device_config *owner, UINT32 clock, device_get_config_func get_config);
public:
INT64 get_config_int(UINT32 state) const { return get_legacy_config_int(state); }
genf *get_config_fct(UINT32 state) const { return get_legacy_config_fct(state); }
void *get_config_ptr(UINT32 state) const { return get_legacy_config_ptr(state); }
};
// ======================> legacy_cart_slot_device
// legacy_cart_slot_device is a legacy_device_base with a cart_slot interface
class legacy_cart_slot_device_base : public legacy_device_base,
public device_cart_slot_interface
{
protected:
// construction/destruction
legacy_cart_slot_device_base(running_machine &machine, const device_config &config);
// device_cart_slot_interface overrides
};
#endif /* __cart_slot_H__ */

452
src/emu/imagedev/cassette.c Normal file
View File

@ -0,0 +1,452 @@
/*********************************************************************
cassette.c
MESS interface to the cassette image abstraction code
*********************************************************************/
#include "emu.h"
#include "imageutl.h"
#include "cassette.h"
#include "cassimg.h"
#include "ui.h"
#define CASSETTE_TAG "cassette"
#define ANIMATION_FPS 1
#define ANIMATION_FRAMES 4
#define VERBOSE 0
#define LOG(x) do { if (VERBOSE) logerror x; } while (0)
typedef struct _dev_cassette_t dev_cassette_t;
struct _dev_cassette_t
{
const cassette_config *config;
cassette_image *cassette;
cassette_state state;
double position;
double position_time;
INT32 value;
};
/* Default cassette_config for drivers only wav files */
const cassette_config default_cassette_config =
{
cassette_default_formats,
NULL,
CASSETTE_PLAY,
NULL
};
INLINE dev_cassette_t *get_safe_token(device_t *device)
{
assert( device != NULL );
assert( device->type() == CASSETTE );
return (dev_cassette_t *) downcast<legacy_device_base *>(device)->token();
}
/*********************************************************************
cassette IO
*********************************************************************/
INLINE int cassette_is_motor_on(device_t *device)
{
dev_cassette_t *cassette = get_safe_token( device );
if ((cassette->state & CASSETTE_MASK_UISTATE) == CASSETTE_STOPPED)
return FALSE;
if ((cassette->state & CASSETTE_MASK_MOTOR) != CASSETTE_MOTOR_ENABLED)
return FALSE;
return TRUE;
}
static void cassette_update(device_t *device)
{
dev_cassette_t *cassette = get_safe_token( device );
double cur_time = attotime_to_double(timer_get_time(device->machine));
if (cassette_is_motor_on(device))
{
double new_position = cassette->position + (cur_time - cassette->position_time);
switch(cassette->state & CASSETTE_MASK_UISTATE) {
case CASSETTE_RECORD:
cassette_put_sample(cassette->cassette, 0, cassette->position, new_position - cassette->position, cassette->value);
break;
case CASSETTE_PLAY:
if ( cassette->cassette )
{
cassette_get_sample(cassette->cassette, 0, new_position, 0.0, &cassette->value);
/* See if reached end of tape */
double length = cassette_get_length(device);
if (new_position > length)
{
cassette->state = (cassette_state)(( cassette->state & ~CASSETTE_MASK_UISTATE ) | CASSETTE_STOPPED);
new_position = length;
}
}
break;
}
cassette->position = new_position;
}
cassette->position_time = cur_time;
}
cassette_state cassette_get_state(device_t *device)
{
dev_cassette_t *cassette = get_safe_token( device );
return cassette->state;
}
void cassette_change_state(device_t *device, cassette_state state, cassette_state mask)
{
dev_cassette_t *cassette = get_safe_token( device );
cassette_state new_state;
new_state = cassette->state;
new_state = (cassette_state)(new_state & ~mask);
new_state = (cassette_state)(new_state | (state & mask));
if (new_state != cassette->state)
{
cassette_update(device);
cassette->state = new_state;
}
}
void cassette_set_state(device_t *device, cassette_state state)
{
cassette_change_state(device, state, (cassette_state)(~0));
}
double cassette_input(device_t *device)
{
dev_cassette_t *cassette = get_safe_token( device );
INT32 sample;
double double_value;
cassette_update(device);
sample = cassette->value;
double_value = sample / ((double) 0x7FFFFFFF);
LOG(("cassette_input(): time_index=%g value=%g\n", cassette->position, double_value));
return double_value;
}
void cassette_output(device_t *device, double value)
{
dev_cassette_t *cassette = get_safe_token( device );
if (((cassette->state & CASSETTE_MASK_UISTATE) == CASSETTE_RECORD) && (cassette->value != value))
{
cassette_update(device);
value = MIN(value, 1.0);
value = MAX(value, -1.0);
cassette->value = (INT32) (value * 0x7FFFFFFF);
}
}
cassette_image *cassette_get_image(device_t *device)
{
dev_cassette_t *cassette = get_safe_token( device );
return cassette->cassette;
}
double cassette_get_position(device_t *device)
{
dev_cassette_t *cassette = get_safe_token( device );
double position;
position = cassette->position;
if (cassette_is_motor_on(device))
position += attotime_to_double(timer_get_time(device->machine)) - cassette->position_time;
return position;
}
double cassette_get_length(device_t *device)
{
dev_cassette_t *cassette = get_safe_token( device );
struct CassetteInfo info;
cassette_get_info(cassette->cassette, &info);
return ((double) info.sample_count) / info.sample_frequency;
}
void cassette_seek(device_t *device, double time, int origin)
{
dev_cassette_t *cassette = get_safe_token( device );
double length;
cassette_update(device);
length = cassette_get_length(device);
switch(origin) {
case SEEK_SET:
break;
case SEEK_END:
time += length;
break;
case SEEK_CUR:
time += cassette_get_position(device);
break;
}
/* clip position into legal bounds */
if (time < 0)
time = 0;
else
if (time > length)
time = length;
cassette->position = time;
}
/*********************************************************************
cassette device init/load/unload/specify
*********************************************************************/
static DEVICE_START( cassette )
{
dev_cassette_t *cassette = get_safe_token( device );
/* set to default state */
cassette->config = (const cassette_config*)device->baseconfig().static_config();
cassette->cassette = NULL;
cassette->state = cassette->config->default_state;
}
static DEVICE_IMAGE_LOAD( cassette )
{
device_t *device = &image.device();
dev_cassette_t *cassette = get_safe_token( device );
casserr_t err;
int cassette_flags;
const struct CassetteFormat * const *formats;
const struct CassetteOptions *create_opts;
const char *extension;
int is_writable;
/* figure out the cassette format */
formats = cassette->config->formats;
if (image.has_been_created())
{
/* creating an image */
create_opts = cassette->config->create_opts;
err = cassette_create(device->machine, (void *) &image, &image_ioprocs, &wavfile_format, create_opts, CASSETTE_FLAG_READWRITE|CASSETTE_FLAG_SAVEONEXIT, &cassette->cassette);
if (err)
goto error;
}
else
{
/* opening an image */
do
{
is_writable = image.is_writable();
cassette_flags = is_writable ? (CASSETTE_FLAG_READWRITE|CASSETTE_FLAG_SAVEONEXIT) : CASSETTE_FLAG_READONLY;
extension = image.filetype();
err = cassette_open_choices(device->machine,(void *) &image, &image_ioprocs, extension, formats, cassette_flags, &cassette->cassette);
/* this is kind of a hack */
if (err && is_writable)
image.make_readonly();
}
while(err && is_writable);
if (err)
goto error;
}
/* set to default state, but only change the UI state */
cassette_change_state(device, cassette->config->default_state, CASSETTE_MASK_UISTATE);
/* reset the position */
cassette->position = 0.0;
cassette->position_time = attotime_to_double(timer_get_time(device->machine));
return IMAGE_INIT_PASS;
error:
return IMAGE_INIT_FAIL;
}
static DEVICE_IMAGE_UNLOAD( cassette )
{
device_t *device = &image.device();
dev_cassette_t *cassette = get_safe_token( device );
/* if we are recording, write the value to the image */
if ((cassette->state & CASSETTE_MASK_UISTATE) == CASSETTE_RECORD)
cassette_update(device);
/* close out the cassette */
cassette_close(cassette->cassette);
cassette->cassette = NULL;
/* set to default state, but only change the UI state */
cassette_change_state(device, CASSETTE_STOPPED, CASSETTE_MASK_UISTATE);
}
/*
display a small tape icon, with the current position in the tape image
*/
static DEVICE_IMAGE_DISPLAY(cassette)
{
device_t *device = &image.device();
char buf[65];
float x, y;
int n;
double position, length;
cassette_state uistate;
device_t *dev;
static const UINT8 shapes[8] = { 0x2d, 0x5c, 0x7c, 0x2f, 0x2d, 0x20, 0x20, 0x20 };
/* abort if we should not be showing the image */
if (!image.exists())
return;
if (!cassette_is_motor_on(device))
return;
/* figure out where we are in the cassette */
position = cassette_get_position(device);
length = cassette_get_length(device);
uistate = (cassette_state)(cassette_get_state(device) & CASSETTE_MASK_UISTATE);
/* choose a location on the screen */
x = 0.2f;
y = 0.5f;
dev = device->machine->m_devicelist.first(CASSETTE );
while ( dev && strcmp( dev->tag(), device->tag() ) )
{
y += 1;
dev = dev->typenext();
}
y *= ui_get_line_height(*device->machine) + 2.0f * UI_BOX_TB_BORDER;
/* choose which frame of the animation we are at */
n = ((int) position / ANIMATION_FPS) % ANIMATION_FRAMES;
/* Since you can have anything in a BDF file, we will use crude ascii characters instead */
snprintf(buf, ARRAY_LENGTH(buf), "%c%c %c %02d:%02d (%04d) [%02d:%02d (%04d)]",
#if 0
/* THE ANIMATION HASN'T WORKED SINCE 0.114 - LEFT HERE FOR REFERENCE */
/* NEVER SEEN THE PLAY / RECORD ICONS */
/* character pairs 2-3, 4-5, 6-7, 8-9 form little tape cassette images */
n * 2 + 2, /* cassette icon left */
n * 2 + 3, /* cassette icon right */
(uistate == CASSETTE_PLAY) ? 16 : 14, /* play or record icon */
#else
shapes[n], /* cassette icon left */
shapes[n|4], /* cassette icon right */
(uistate == CASSETTE_PLAY) ? 0x50 : 0x52, /* play (P) or record (R) */
#endif
((int) position / 60),
((int) position % 60),
(int) position,
((int) length / 60),
((int) length % 60),
(int) length);
/* draw the cassette */
ui_draw_text_box(&device->machine->render().ui_container(), buf, JUSTIFY_LEFT, x, y, UI_BACKGROUND_COLOR);
}
/*-------------------------------------------------
DEVICE_IMAGE_SOFTLIST_LOAD(cassette)
-------------------------------------------------*/
static DEVICE_IMAGE_SOFTLIST_LOAD(cassette)
{
return image.load_software(swlist, swname, start_entry);
}
DEVICE_GET_INFO(cassette)
{
switch( state )
{
/* --- the following bits of info are returned as 64-bit signed integers --- */
case DEVINFO_INT_TOKEN_BYTES: info->i = sizeof(dev_cassette_t); break;
case DEVINFO_INT_INLINE_CONFIG_BYTES: info->i = 0; break;
case DEVINFO_INT_IMAGE_TYPE: info->i = IO_CASSETTE; break;
case DEVINFO_INT_IMAGE_READABLE: info->i = 1; break;
case DEVINFO_INT_IMAGE_WRITEABLE: info->i = 1; break;
case DEVINFO_INT_IMAGE_CREATABLE: info->i = 1; break;
/* --- the following bits of info are returned as pointers to data or functions --- */
case DEVINFO_FCT_START: info->start = DEVICE_START_NAME(cassette); break;
case DEVINFO_FCT_IMAGE_LOAD: info->f = (genf *) DEVICE_IMAGE_LOAD_NAME(cassette); break;
case DEVINFO_FCT_IMAGE_UNLOAD: info->f = (genf *) DEVICE_IMAGE_UNLOAD_NAME(cassette); break;
case DEVINFO_FCT_IMAGE_DISPLAY: info->f = (genf *) DEVICE_IMAGE_DISPLAY_NAME(cassette); break;
case DEVINFO_FCT_IMAGE_SOFTLIST_LOAD: info->f = (genf *) DEVICE_IMAGE_SOFTLIST_LOAD_NAME(cassette); break;
/* --- the following bits of info are returned as NULL-terminated strings --- */
case DEVINFO_STR_NAME: strcpy(info->s, "Cassette"); break;
case DEVINFO_STR_FAMILY: strcpy(info->s, "Cassette"); break;
case DEVINFO_STR_SOURCE_FILE: strcpy(info->s, __FILE__); break;
case DEVINFO_STR_IMAGE_FILE_EXTENSIONS:
if ( device && device->static_config() )
{
const struct CassetteFormat * const *formats = ((cassette_config *)device->static_config())->formats;
int i;
/* set up a temporary string */
info->s[0] = '\0';
for ( i = 0; formats[i]; i++ )
image_specify_extension( info->s, 256, formats[i]->extensions );
}
break;
case DEVINFO_STR_IMAGE_INTERFACE:
if ( device && device->static_config() && ((cassette_config *)device->static_config())->interface)
{
strcpy(info->s, ((cassette_config *)device->static_config())->interface );
}
break;
}
}
DEFINE_LEGACY_IMAGE_DEVICE(CASSETTE, cassette);

View File

@ -0,0 +1,85 @@
/*********************************************************************
cassette.h
MESS interface to the cassette image abstraction code
*********************************************************************/
#ifndef CASSETTE_H
#define CASSETTE_H
#include "image.h"
#include "cassimg.h"
enum _cassette_state
{
/* this part of the state is controlled by the UI */
CASSETTE_STOPPED = 0,
CASSETTE_PLAY = 1,
CASSETTE_RECORD = 2,
/* this part of the state is controlled by drivers */
CASSETTE_MOTOR_ENABLED = 0,
CASSETTE_MOTOR_DISABLED = 4,
CASSETTE_SPEAKER_ENABLED = 0,
CASSETTE_SPEAKER_MUTED = 8,
/* masks */
CASSETTE_MASK_UISTATE = 3,
CASSETTE_MASK_MOTOR = 4,
CASSETTE_MASK_SPEAKER = 8,
CASSETTE_MASK_DRVSTATE = 12
};
typedef enum _cassette_state cassette_state;
/***************************************************************************
TYPE DEFINITIONS
***************************************************************************/
typedef struct cassette_config_t cassette_config;
struct cassette_config_t
{
const struct CassetteFormat* const *formats;
const struct CassetteOptions *create_opts;
const cassette_state default_state;
const char * interface;
};
/***************************************************************************
FUNCTION PROTOTYPES
***************************************************************************/
cassette_state cassette_get_state(device_t *cassette);
void cassette_set_state(device_t *cassette, cassette_state state);
void cassette_change_state(device_t *cassette, cassette_state state, cassette_state mask);
double cassette_input(device_t *cassette);
void cassette_output(device_t *cassette, double value);
cassette_image *cassette_get_image(device_t *cassette);
double cassette_get_position(device_t *cassette);
double cassette_get_length(device_t *cassette);
void cassette_seek(device_t *cassette, double time, int origin);
DECLARE_LEGACY_IMAGE_DEVICE(CASSETTE, cassette);
/***************************************************************************
DEVICE CONFIGURATION MACROS
***************************************************************************/
#define MCFG_CASSETTE_ADD(_tag, _config) \
MCFG_DEVICE_ADD(_tag, CASSETTE, 0) \
MCFG_DEVICE_CONFIG(_config)
#define MCFG_CASSETTE_MODIFY(_tag, _config) \
MCFG_DEVICE_MODIFY(_tag) \
MCFG_DEVICE_CONFIG(_config)
extern const cassette_config default_cassette_config;
#endif /* CASSETTE_H */

1059
src/emu/imagedev/cassimg.c Normal file

File diff suppressed because it is too large Load Diff

227
src/emu/imagedev/cassimg.h Normal file
View File

@ -0,0 +1,227 @@
/*********************************************************************
cassimg.h
Cassette tape image abstraction code
*********************************************************************/
#ifndef CASSIMG_H
#define CASSIMG_H
#include "pool.h"
#include "emu.h"
/***************************************************************************
Constants
***************************************************************************/
#define CASSETTE_FLAG_READWRITE 0
#define CASSETTE_FLAG_READONLY 1
#define CASSETTE_FLAG_NOSAVEONEXIT 0
#define CASSETTE_FLAG_SAVEONEXIT 2
#define CASSETTE_WAVEFORM_8BIT 0
#define CASSETTE_WAVEFORM_16BIT 2
#define CASSETTE_WAVEFORM_16BIT_FLIP 3
#define CASSETTE_WAVEFORM_32BIT 4
#define CASSETTE_WAVEFORM_32BIT_FLIP 5
#define CASSETTE_WAVEFORM_ENDIAN_FLIP 1
#define CASSETTE_MODULATION_SQUAREWAVE 0
#define CASSETTE_MODULATION_SINEWAVE 1
#ifdef LSB_FIRST
#define CASSETTE_WAVEFORM_16BITBE CASSETTE_WAVEFORM_16BIT_FLIP
#define CASSETTE_WAVEFORM_16BITLE CASSETTE_WAVEFORM_16BIT
#define CASSETTE_WAVEFORM_32BITBE CASSETTE_WAVEFORM_32BIT_FLIP
#define CASSETTE_WAVEFORM_32BITLE CASSETTE_WAVEFORM_32BIT
#else
#define CASSETTE_WAVEFORM_16BITBE CASSETTE_WAVEFORM_16BIT
#define CASSETTE_WAVEFORM_16BITLE CASSETTE_WAVEFORM_16BIT_FLIP
#define CASSETTE_WAVEFORM_32BITBE CASSETTE_WAVEFORM_32BIT
#define CASSETTE_WAVEFORM_32BITLE CASSETTE_WAVEFORM_32BIT_FLIP
#endif
/***************************************************************************
Type definitions
***************************************************************************/
typedef enum
{
CASSETTE_ERROR_SUCCESS, /* no error */
CASSETTE_ERROR_INTERNAL, /* fatal internal error */
CASSETTE_ERROR_UNSUPPORTED, /* this operation is unsupported */
CASSETTE_ERROR_OUTOFMEMORY, /* ran out of memory */
CASSETTE_ERROR_INVALIDIMAGE, /* invalid image */
CASSETTE_ERROR_INVALIDARG
}
casserr_t;
struct sample_block
{
INT32 *block;
size_t sample_count;
};
struct CassetteOptions
{
int channels;
int bits_per_sample;
UINT32 sample_frequency;
};
struct CassetteInfo
{
int channels;
int bits_per_sample;
UINT32 sample_frequency;
size_t sample_count;
};
struct _cassette_image
{
const struct CassetteFormat *format;
struct io_generic io;
object_pool *pool;
int channels;
int flags;
UINT32 sample_frequency;
struct sample_block *blocks;
size_t block_count;
size_t sample_count;
running_machine *machine;
};
typedef struct _cassette_image cassette_image;
struct CassetteFormat
{
const char *extensions;
casserr_t (*identify)(cassette_image *cassette, struct CassetteOptions *opts);
casserr_t (*load)(cassette_image *cassette);
casserr_t (*save)(cassette_image *cassette, const struct CassetteInfo *info);
};
/* used for the core modulation code */
struct CassetteModulation
{
int flags;
double zero_frequency_low;
double zero_frequency_cannonical;
double zero_frequency_high;
double one_frequency_low;
double one_frequency_cannonical;
double one_frequency_high;
};
/* code to adapt existing legacy fill_wave functions */
struct CassetteLegacyWaveFiller
{
int (*fill_wave)(INT16 *, int, UINT8 *);
int chunk_size;
int chunk_samples;
int (*chunk_sample_calc)(const UINT8 *bytes, int length);
UINT32 sample_frequency;
int header_samples;
int trailer_samples;
};
/* builtin formats */
extern const struct CassetteFormat wavfile_format;
/* macros for specifying format lists */
#define CASSETTE_FORMATLIST_EXTERN(name) \
extern const struct CassetteFormat *const name[]
#define CASSETTE_FORMATLIST_START(name) \
const struct CassetteFormat *const name[] = \
{ \
&wavfile_format, \
#define CASSETTE_FORMAT(name) \
&(name), \
#define CASSETTE_FORMATLIST_END \
NULL \
};
CASSETTE_FORMATLIST_EXTERN(cassette_default_formats);
/***************************************************************************
Prototypes
***************************************************************************/
casserr_t cassette_open(running_machine *machine,void *file, const struct io_procs *procs,
const struct CassetteFormat *format, int flags, cassette_image **outcassette);
casserr_t cassette_open_choices(running_machine *machine,void *file, const struct io_procs *procs, const char *extension,
const struct CassetteFormat *const *formats, int flags, cassette_image **outcassette);
casserr_t cassette_create(running_machine *machine,void *file, const struct io_procs *procs, const struct CassetteFormat *format,
const struct CassetteOptions *opts, int flags, cassette_image **outcassette);
casserr_t cassette_save(cassette_image *cassette);
void cassette_close(cassette_image *cassette);
void cassette_change(cassette_image *cassette, void *file, const struct io_procs *procs, const struct CassetteFormat *format, int flags);
void cassette_get_info(cassette_image *cassette, struct CassetteInfo *info);
/* calls for accessing the raw cassette image */
void cassette_image_read(cassette_image *cassette, void *buffer, UINT64 offset, size_t length);
void cassette_image_write(cassette_image *cassette, const void *buffer, UINT64 offset, size_t length);
UINT64 cassette_image_size(cassette_image *cassette);
/* waveform accesses */
casserr_t cassette_get_samples(cassette_image *cassette, int channel,
double time_index, double sample_period, size_t sample_count, size_t sample_bytes,
void *samples, int waveform_flags);
casserr_t cassette_put_samples(cassette_image *cassette, int channel,
double time_index, double sample_period, size_t sample_count, size_t sample_bytes,
const void *samples, int waveform_flags);
casserr_t cassette_get_sample(cassette_image *cassette, int channel,
double time_index, double sample_period, INT32 *sample);
casserr_t cassette_put_sample(cassette_image *cassette, int channel,
double time_index, double sample_period, INT32 sample);
/* waveform accesses to/from the raw image */
casserr_t cassette_read_samples(cassette_image *cassette, int channels, double time_index,
double sample_period, size_t sample_count, UINT64 offset, int waveform_flags);
casserr_t cassette_write_samples(cassette_image *cassette, int channels, double time_index,
double sample_period, size_t sample_count, UINT64 offset, int waveform_flags);
/* modulation support */
casserr_t cassette_modulation_identify(cassette_image *cassette, const struct CassetteModulation *modulation,
struct CassetteOptions *opts);
casserr_t cassette_put_modulated_data(cassette_image *cassette, int channel, double time_index,
const void *data, size_t data_length, const struct CassetteModulation *modulation,
double *time_displacement);
casserr_t cassette_put_modulated_filler(cassette_image *cassette, int channel, double time_index,
UINT8 filler, size_t filler_length, const struct CassetteModulation *modulation,
double *time_displacement);
casserr_t cassette_read_modulated_data(cassette_image *cassette, int channel, double time_index,
UINT64 offset, UINT64 length, const struct CassetteModulation *modulation,
double *time_displacement);
casserr_t cassette_put_modulated_data_bit(cassette_image *cassette, int channel, double time_index,
UINT8 data, const struct CassetteModulation *modulation,
double *time_displacement);
/* debug calls */
void cassette_dump(cassette_image *image, const char *filename);
/* legacy code support */
#define CODE_HEADER ((UINT8*)-1)
#define CODE_TRAILER ((UINT8*)-2)
casserr_t cassette_legacy_identify(cassette_image *cassette, struct CassetteOptions *opts,
const struct CassetteLegacyWaveFiller *legacy_args);
casserr_t cassette_legacy_construct(cassette_image *cassette,
const struct CassetteLegacyWaveFiller *legacy_args);
#endif /* CASSIMG_H */

191
src/emu/imagedev/chd_cd.c Normal file
View File

@ -0,0 +1,191 @@
/*********************************************************************
Code to interface the MESS image code with MAME's CHD-CD core.
Based on harddriv.c by Raphael Nabet 2003
*********************************************************************/
#include "emu.h"
#include "cdrom.h"
#include "chd_cd.h"
static const char *const error_strings[] =
{
"no error",
"no drive interface",
"out of memory",
"invalid file",
"invalid parameter",
"invalid data",
"file not found",
"requires parent",
"file not writeable",
"read error",
"write error",
"codec error",
"invalid parent",
"hunk out of range",
"decompression error",
"compression error",
"can't create file",
"can't verify file"
"operation not supported",
"can't find metadata",
"invalid metadata size",
"unsupported CHD version"
};
INLINE const cdrom_config *get_config_dev(const device_config *device)
{
assert(device != NULL);
assert(device->type() == CDROM);
return (const cdrom_config *)downcast<const legacy_device_config_base *>(device)->inline_config();
}
static const char *chd_get_error_string(int chderr)
{
if ((chderr < 0 ) || (chderr >= ARRAY_LENGTH(error_strings)))
return NULL;
return error_strings[chderr];
}
static OPTION_GUIDE_START(mess_cd_option_guide)
OPTION_INT('K', "hunksize", "Hunk Bytes")
OPTION_GUIDE_END
static const char mess_cd_option_spec[] =
"K512/1024/2048/[4096]";
typedef struct _dev_cdrom_t dev_cdrom_t;
struct _dev_cdrom_t
{
cdrom_file *cdrom_handle;
};
INLINE dev_cdrom_t *get_safe_token(device_t *device) {
assert( device != NULL );
assert( ( device->type() == CDROM ) );
return (dev_cdrom_t *) downcast<legacy_device_base *>(device)->token();
}
static DEVICE_IMAGE_LOAD(cdrom)
{
dev_cdrom_t *cdrom = get_safe_token(&image.device());
chd_error err = (chd_error)0;
chd_file *chd = NULL;
err = chd_open_file( image.image_core_file(), CHD_OPEN_READ, NULL, &chd ); /* CDs are never writeable */
if ( err )
goto error;
/* open the CHD file */
cdrom->cdrom_handle = cdrom_open( chd );
if ( ! cdrom->cdrom_handle )
goto error;
return IMAGE_INIT_PASS;
error:
if ( chd )
chd_close( chd );
if ( err )
image.seterror( IMAGE_ERROR_UNSPECIFIED, chd_get_error_string( err ) );
return IMAGE_INIT_FAIL;
}
static DEVICE_IMAGE_UNLOAD(cdrom)
{
dev_cdrom_t *cdrom = get_safe_token( &image.device() );
assert( cdrom->cdrom_handle );
cdrom_close( cdrom->cdrom_handle );
cdrom->cdrom_handle = NULL;
}
/*************************************
*
* Get the MESS/MAME cdrom handle (from the src/cdrom.c core)
* after an image has been opened with the mess_cd core
*
*************************************/
cdrom_file *mess_cd_get_cdrom_file(device_t *image)
{
dev_cdrom_t *cdrom = get_safe_token( image );
return cdrom->cdrom_handle;
}
/*-------------------------------------------------
DEVICE_START(cdrom)
-------------------------------------------------*/
static DEVICE_START(cdrom)
{
dev_cdrom_t *cdrom = get_safe_token( device );
cdrom->cdrom_handle = NULL;
}
/*-------------------------------------------------
DEVICE_IMAGE_SOFTLIST_LOAD(cdrom)
-------------------------------------------------*/
static DEVICE_IMAGE_SOFTLIST_LOAD(cdrom)
{
return image.load_software(swlist, swname, start_entry);
}
/*-------------------------------------------------
DEVICE_GET_INFO(cdrom)
-------------------------------------------------*/
DEVICE_GET_INFO(cdrom)
{
switch( state )
{
/* --- the following bits of info are returned as 64-bit signed integers --- */
case DEVINFO_INT_TOKEN_BYTES: info->i = sizeof(dev_cdrom_t); break;
case DEVINFO_INT_INLINE_CONFIG_BYTES: info->i = sizeof(cdrom_config); break;
case DEVINFO_INT_IMAGE_TYPE: info->i = IO_CDROM; break;
case DEVINFO_INT_IMAGE_READABLE: info->i = 1; break;
case DEVINFO_INT_IMAGE_WRITEABLE: info->i = 0; break;
case DEVINFO_INT_IMAGE_CREATABLE: info->i = 0; break;
case DEVINFO_INT_IMAGE_CREATE_OPTCOUNT: info->i = 1; break;
/* --- the following bits of info are returned as pointers to data or functions --- */
case DEVINFO_FCT_START: info->start = DEVICE_START_NAME(cdrom); break;
case DEVINFO_FCT_IMAGE_LOAD: info->f = (genf *) DEVICE_IMAGE_LOAD_NAME(cdrom); break;
case DEVINFO_FCT_IMAGE_UNLOAD: info->f = (genf *) DEVICE_IMAGE_UNLOAD_NAME(cdrom); break;
case DEVINFO_FCT_IMAGE_SOFTLIST_LOAD: info->f = (genf *) DEVICE_IMAGE_SOFTLIST_LOAD_NAME(cdrom); break;
case DEVINFO_PTR_IMAGE_CREATE_OPTGUIDE: info->p = (void *) mess_cd_option_guide; break;
case DEVINFO_PTR_IMAGE_CREATE_OPTSPEC+0: info->p = (void *) mess_cd_option_spec; break;
/* --- the following bits of info are returned as NULL-terminated strings --- */
case DEVINFO_STR_NAME: strcpy(info->s, "Cdrom"); break;
case DEVINFO_STR_FAMILY: strcpy(info->s, "Cdrom"); break;
case DEVINFO_STR_SOURCE_FILE: strcpy(info->s, __FILE__); break;
case DEVINFO_STR_IMAGE_FILE_EXTENSIONS: strcpy(info->s, "chd"); break;
case DEVINFO_STR_IMAGE_CREATE_OPTNAME+0: strcpy(info->s, "chdcd"); break;
case DEVINFO_STR_IMAGE_CREATE_OPTDESC+0: strcpy(info->s, "MAME/MESS CHD CD-ROM drive"); break;
case DEVINFO_STR_IMAGE_CREATE_OPTEXTS+0: strcpy(info->s, "chd"); break;
case DEVINFO_STR_IMAGE_INTERFACE:
if ( device && downcast<const legacy_image_device_config_base *>(device)->inline_config() && get_config_dev(device)->interface )
{
strcpy(info->s, get_config_dev(device)->interface );
}
break;
}
}
DEFINE_LEGACY_IMAGE_DEVICE(CDROM, cdrom);

43
src/emu/imagedev/chd_cd.h Normal file
View File

@ -0,0 +1,43 @@
/*********************************************************************
chd_cd.h
MESS interface to the MAME CHD CDROM code
*********************************************************************/
#ifndef MESS_CD_H
#define MESS_CD_H
#include "cdrom.h"
/***************************************************************************
TYPE DEFINITIONS
***************************************************************************/
typedef struct cdrom_config_t cdrom_config;
struct cdrom_config_t
{
const char * interface;
};
/***************************************************************************
FUNCTION PROTOTYPES
***************************************************************************/
DECLARE_LEGACY_IMAGE_DEVICE(CDROM, cdrom);
cdrom_file *mess_cd_get_cdrom_file(device_t *device);
/***************************************************************************
DEVICE CONFIGURATION MACROS
***************************************************************************/
#define MCFG_CDROM_ADD(_tag) \
MCFG_DEVICE_ADD(_tag, CDROM, 0) \
#define MCFG_CDROM_INTERFACE(_interface) \
MCFG_DEVICE_CONFIG_DATAPTR(cdrom_config, interface, _interface )
#endif /* MESS_CD_H */

1045
src/emu/imagedev/flopdrv.c Normal file

File diff suppressed because it is too large Load Diff

245
src/emu/imagedev/flopdrv.h Normal file
View File

@ -0,0 +1,245 @@
/* flopdrv provides simple emulation of a disc drive */
/* the 8271, upd765 and wd179x use this */
#ifndef __FLOPDRV_H__
#define __FLOPDRV_H__
#include "devcb.h"
#include "image.h"
#include "flopimg.h"
#define FLOPPY_TYPE_REGULAR 0
#define FLOPPY_TYPE_APPLE 1
#define FLOPPY_TYPE_SONY 2
#define FLOPPY_DRIVE_2_8_INCH 1
#define FLOPPY_DRIVE_3_INCH 2
#define FLOPPY_DRIVE_3_5_INCH 3
#define FLOPPY_DRIVE_5_25_INCH 4
#define FLOPPY_DRIVE_8_INCH 5
// Maximum supported density
#define FLOPPY_DRIVE_SD 1
#define FLOPPY_DRIVE_DD 2
#define FLOPPY_DRIVE_QD 3
#define FLOPPY_DRIVE_HD 4
#define FLOPPY_DRIVE_ED 5
#define FLOPPY_STANDARD_3_SSDD { FLOPPY_DRIVE_3_INCH, 1, 42, FLOPPY_DRIVE_DD }
#define FLOPPY_STANDARD_3_DSDD { FLOPPY_DRIVE_3_INCH, 2, 42, FLOPPY_DRIVE_DD }
#define FLOPPY_STANDARD_3_5_DSDD { FLOPPY_DRIVE_3_5_INCH, 2, 83, FLOPPY_DRIVE_DD }
#define FLOPPY_STANDARD_3_5_DSHD { FLOPPY_DRIVE_3_5_INCH, 2, 83, FLOPPY_DRIVE_HD }
#define FLOPPY_STANDARD_5_25_SSSD_35 { FLOPPY_DRIVE_5_25_INCH, 1, 37, FLOPPY_DRIVE_SD }
#define FLOPPY_STANDARD_5_25_DSSD_35 { FLOPPY_DRIVE_5_25_INCH, 2, 37, FLOPPY_DRIVE_SD }
#define FLOPPY_STANDARD_5_25_SSSD { FLOPPY_DRIVE_5_25_INCH, 1, 42, FLOPPY_DRIVE_SD }
#define FLOPPY_STANDARD_5_25_DSSD { FLOPPY_DRIVE_5_25_INCH, 2, 42, FLOPPY_DRIVE_SD }
#define FLOPPY_STANDARD_5_25_SSDD_40 { FLOPPY_DRIVE_5_25_INCH, 1, 42, FLOPPY_DRIVE_DD }
#define FLOPPY_STANDARD_5_25_DSDD_40 { FLOPPY_DRIVE_5_25_INCH, 2, 42, FLOPPY_DRIVE_DD }
#define FLOPPY_STANDARD_5_25_SSDD { FLOPPY_DRIVE_5_25_INCH, 1, 83, FLOPPY_DRIVE_DD }
#define FLOPPY_STANDARD_5_25_DSDD { FLOPPY_DRIVE_5_25_INCH, 2, 83, FLOPPY_DRIVE_DD }
#define FLOPPY_STANDARD_5_25_DSQD { FLOPPY_DRIVE_5_25_INCH, 2, 83, FLOPPY_DRIVE_QD }
#define FLOPPY_STANDARD_5_25_DSHD { FLOPPY_DRIVE_5_25_INCH, 2, 83, FLOPPY_DRIVE_HD }
#define FLOPPY_STANDARD_8_SSSD { FLOPPY_DRIVE_8_INCH, 1, 77, FLOPPY_DRIVE_SD }
#define FLOPPY_STANDARD_8_DSSD { FLOPPY_DRIVE_8_INCH, 2, 77, FLOPPY_DRIVE_SD }
#define FLOPPY_STANDARD_8_DSDD { FLOPPY_DRIVE_8_INCH, 2, 77, FLOPPY_DRIVE_DD }
/***************************************************************************
TYPE DEFINITIONS
***************************************************************************/
typedef struct floppy_type_t floppy_type;
struct floppy_type_t
{
UINT8 media_size;
UINT8 head_number;
UINT8 max_track_number;
UINT8 max_density;
};
typedef struct floppy_config_t floppy_config;
struct floppy_config_t
{
devcb_write_line out_idx_func; /* index */
devcb_read_line in_mon_func; /* motor on */
devcb_write_line out_tk00_func; /* track 00 */
devcb_write_line out_wpt_func; /* write protect */
devcb_write_line out_rdy_func; /* ready */
// devcb_write_line out_dskchg_func; /* disk changed */
floppy_type_t floppy_type;
const struct FloppyFormat *formats;
const char *interface;
};
/* sector has a deleted data address mark */
#define ID_FLAG_DELETED_DATA 0x0001
/* CRC error in id field */
#define ID_FLAG_CRC_ERROR_IN_ID_FIELD 0x0002
/* CRC error in data field */
#define ID_FLAG_CRC_ERROR_IN_DATA_FIELD 0x0004
typedef struct chrn_id
{
unsigned char C;
unsigned char H;
unsigned char R;
unsigned char N;
int data_id; // id for read/write data command
unsigned long flags;
} chrn_id;
/* set if drive is ready */
#define FLOPPY_DRIVE_READY 0x0010
/* set if index has just occured */
#define FLOPPY_DRIVE_INDEX 0x0020
/* a callback which will be executed if the ready state of the drive changes e.g. not ready->ready, ready->not ready */
void floppy_drive_set_ready_state_change_callback(device_t *img, void (*callback)(device_t *controller,device_t *img, int state));
void floppy_drive_set_index_pulse_callback(device_t *img, void (*callback)(device_t *controller,device_t *image, int state));
/* set flag state */
int floppy_drive_get_flag_state(device_t *img, int flag);
/* get flag state */
void floppy_drive_set_flag_state(device_t *img, int flag, int state);
/* get current physical track drive is on */
int floppy_drive_get_current_track(device_t *img);
/* get current physical track size */
UINT64 floppy_drive_get_current_track_size(device_t *img, int head);
/* get next id from track, 1 if got a id, 0 if no id was got */
int floppy_drive_get_next_id(device_t *img, int side, chrn_id *);
/* set ready state of drive. If flag == 1, set ready state only if drive present,
disk is in drive, and motor is on. Otherwise set ready state to the state passed */
void floppy_drive_set_ready_state(device_t *img, int state, int flag);
/* seek up or down */
void floppy_drive_seek(device_t *img, signed int signed_tracks);
void floppy_drive_read_track_data_info_buffer(device_t *img, int side, void *ptr, int *length );
void floppy_drive_write_track_data_info_buffer(device_t *img, int side, const void *ptr, int *length );
void floppy_drive_format_sector(device_t *img, int side, int sector_index, int c, int h, int r, int n, int filler);
void floppy_drive_read_sector_data(device_t *img, int side, int index1, void *pBuffer, int length);
void floppy_drive_write_sector_data(device_t *img, int side, int index1, const void *pBuffer, int length, int ddam);
/* set motor speed to get correct index pulses
standard RPM are 300 RPM (common) and 360 RPM
Note: this actually only works for soft sectored disks: one index pulse per
track.
*/
void floppy_drive_set_rpm(device_t *image, float rpm);
void floppy_drive_set_controller(device_t *img, device_t *controller);
floppy_image *flopimg_get_image(device_t *image);
/* hack for apple II; replace this when we think of something better */
void floppy_install_unload_proc(device_t *image, void (*proc)(device_image_interface &image));
void floppy_install_load_proc(device_t *image, void (*proc)(device_image_interface &image));
device_t *floppy_get_device(running_machine *machine,int drive);
device_t *floppy_get_device_by_type(running_machine *machine,int ftype,int drive);
int floppy_get_drive_type(device_t *image);
void floppy_set_type(device_t *image,int ftype);
int floppy_get_count(running_machine *machine);
int floppy_get_drive(device_t *image);
int floppy_get_drive_by_type(device_t *image,int ftype);
void *flopimg_get_custom_data(device_t *image);
void flopimg_alloc_custom_data(device_t *image,void *custom);
void floppy_drive_set_geometry(device_t *img, floppy_type_t type);
/* drive select lines */
WRITE_LINE_DEVICE_HANDLER( floppy_ds0_w );
WRITE_LINE_DEVICE_HANDLER( floppy_ds1_w );
WRITE_LINE_DEVICE_HANDLER( floppy_ds2_w );
WRITE_LINE_DEVICE_HANDLER( floppy_ds3_w );
WRITE8_DEVICE_HANDLER( floppy_ds_w );
WRITE_LINE_DEVICE_HANDLER( floppy_mon_w );
WRITE_LINE_DEVICE_HANDLER( floppy_drtn_w );
WRITE_LINE_DEVICE_HANDLER( floppy_stp_w );
WRITE_LINE_DEVICE_HANDLER( floppy_wtd_w );
WRITE_LINE_DEVICE_HANDLER( floppy_wtg_w );
/* write-protect */
READ_LINE_DEVICE_HANDLER( floppy_wpt_r );
/* track 0 detect */
READ_LINE_DEVICE_HANDLER( floppy_tk00_r );
/* disk changed */
READ_LINE_DEVICE_HANDLER( floppy_dskchg_r );
/* 2-sided disk */
READ_LINE_DEVICE_HANDLER( floppy_twosid_r );
DECLARE_LEGACY_IMAGE_DEVICE(FLOPPY, floppy);
extern DEVICE_START( floppy );
extern DEVICE_IMAGE_LOAD( floppy );
extern DEVICE_IMAGE_CREATE( floppy );
extern DEVICE_IMAGE_UNLOAD( floppy );
/***************************************************************************
DEVICE CONFIGURATION MACROS
***************************************************************************/
#define FLOPPY_0 "floppy0"
#define FLOPPY_1 "floppy1"
#define FLOPPY_2 "floppy2"
#define FLOPPY_3 "floppy3"
#define MCFG_FLOPPY_DRIVE_ADD(_tag, _config) \
MCFG_DEVICE_ADD(_tag, FLOPPY, 0) \
MCFG_DEVICE_CONFIG(_config)
#define MCFG_FLOPPY_DRIVE_MODIFY(_tag, _config) \
MCFG_DEVICE_MODIFY(_tag) \
MCFG_DEVICE_CONFIG(_config)
#define MCFG_FLOPPY_4_DRIVES_ADD(_config) \
MCFG_DEVICE_ADD(FLOPPY_0, FLOPPY, 0) \
MCFG_DEVICE_CONFIG(_config) \
MCFG_DEVICE_ADD(FLOPPY_1, FLOPPY, 0) \
MCFG_DEVICE_CONFIG(_config) \
MCFG_DEVICE_ADD(FLOPPY_2, FLOPPY, 0) \
MCFG_DEVICE_CONFIG(_config) \
MCFG_DEVICE_ADD(FLOPPY_3, FLOPPY, 0) \
MCFG_DEVICE_CONFIG(_config)
#define MCFG_FLOPPY_4_DRIVES_MODIFY(_config) \
MCFG_DEVICE_MODIFY(FLOPPY_0) \
MCFG_DEVICE_CONFIG(_config) \
MCFG_DEVICE_MODIFY(FLOPPY_1) \
MCFG_DEVICE_CONFIG(_config) \
MCFG_DEVICE_MODIFY(FLOPPY_2) \
MCFG_DEVICE_CONFIG(_config) \
MCFG_DEVICE_MODIFY(FLOPPY_3) \
MCFG_DEVICE_CONFIG(_config)
#define MCFG_FLOPPY_4_DRIVES_REMOVE() \
MCFG_DEVICE_REMOVE(FLOPPY_0) \
MCFG_DEVICE_REMOVE(FLOPPY_1) \
MCFG_DEVICE_REMOVE(FLOPPY_2) \
MCFG_DEVICE_REMOVE(FLOPPY_3)
#define MCFG_FLOPPY_2_DRIVES_ADD(_config) \
MCFG_DEVICE_ADD(FLOPPY_0, FLOPPY, 0) \
MCFG_DEVICE_CONFIG(_config) \
MCFG_DEVICE_ADD(FLOPPY_1, FLOPPY, 0) \
MCFG_DEVICE_CONFIG(_config)
#define MCFG_FLOPPY_2_DRIVES_MODIFY(_config) \
MCFG_DEVICE_MODIFY(FLOPPY_0) \
MCFG_DEVICE_CONFIG(_config) \
MCFG_DEVICE_MODIFY(FLOPPY_1) \
MCFG_DEVICE_CONFIG(_config)
#define MCFG_FLOPPY_2_DRIVES_REMOVE() \
MCFG_DEVICE_REMOVE(FLOPPY_0) \
MCFG_DEVICE_REMOVE(FLOPPY_1)
#endif /* __FLOPDRV_H__ */

930
src/emu/imagedev/flopimg.c Normal file
View File

@ -0,0 +1,930 @@
/*********************************************************************
flopimg.c
Floppy disk image abstraction code
*********************************************************************/
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <ctype.h>
#include <assert.h>
#include <limits.h>
#include "osdepend.h"
#include "flopimg.h"
#include "pool.h"
#include "imageutl.h"
#define TRACK_LOADED 0x01
#define TRACK_DIRTY 0x02
struct _floppy_image
{
struct io_generic io;
const struct FloppyFormat *floppy_option;
struct FloppyCallbacks format;
/* loaded track stuff */
int loaded_track_head;
int loaded_track_index;
UINT32 loaded_track_size;
void *loaded_track_data;
UINT8 loaded_track_status;
UINT8 flags;
/* tagging system */
object_pool *tags;
void *tag_data;
};
struct _floppy_params
{
int param;
int value;
};
static floperr_t floppy_track_unload(floppy_image *floppy);
OPTION_GUIDE_START(floppy_option_guide)
OPTION_INT('H', "heads", "Heads")
OPTION_INT('T', "tracks", "Tracks")
OPTION_INT('S', "sectors", "Sectors")
OPTION_INT('L', "sectorlength", "Sector Bytes")
OPTION_INT('I', "interleave", "Interleave")
OPTION_INT('F', "firstsectorid", "First Sector")
OPTION_GUIDE_END
static void floppy_close_internal(floppy_image *floppy, int close_file);
/*********************************************************************
opening, closing and creating of floppy images
*********************************************************************/
/* basic floppy_image initialization common to floppy_open() and floppy_create() */
static floppy_image *floppy_init(void *fp, const struct io_procs *procs, int flags)
{
floppy_image *floppy;
floppy = (floppy_image *)malloc(sizeof(struct _floppy_image));
if (!floppy)
return NULL;
memset(floppy, 0, sizeof(*floppy));
floppy->tags = pool_alloc_lib(NULL);
floppy->tag_data = NULL;
floppy->io.file = fp;
floppy->io.procs = procs;
floppy->io.filler = 0xFF;
floppy->flags = (UINT8) flags;
return floppy;
}
/* main code for identifying and maybe opening a disk image; not exposed
* directly because this function is big and hideous */
static floperr_t floppy_open_internal(void *fp, const struct io_procs *procs, const char *extension,
const struct FloppyFormat *floppy_options, int max_options, int flags, floppy_image **outfloppy,
int *outoption)
{
floperr_t err;
floppy_image *floppy;
int best_option = -1;
int best_vote = 0;
int vote;
size_t i;
floppy = floppy_init(fp, procs, flags);
if (!floppy)
{
err = FLOPPY_ERROR_OUTOFMEMORY;
goto done;
}
/* vote on the best format */
for (i = 0; (i < max_options) && floppy_options[i].construct; i++)
{
if (!extension || !floppy_options[i].extensions || image_find_extension(floppy_options[i].extensions, extension))
{
if (floppy_options[i].identify)
{
vote = 0;
err = floppy_options[i].identify(floppy, &floppy_options[i], &vote);
if (err)
goto done;
}
else
{
vote = 1;
}
/* is this option a better one? */
if (vote > best_vote)
{
best_vote = vote;
best_option = i;
}
}
}
/* did we find a format? */
if (best_option == -1)
{
err = FLOPPY_ERROR_INVALIDIMAGE;
goto done;
}
if (outfloppy)
{
/* call the format constructor */
err = floppy_options[best_option].construct(floppy, &floppy_options[best_option], NULL);
if (err)
goto done;
floppy->floppy_option = &floppy_options[best_option];
}
err = FLOPPY_ERROR_SUCCESS;
done:
/* if we have a floppy disk and we either errored or are not keeping it, close it */
if (floppy && (!outfloppy || err))
{
floppy_close_internal(floppy, FALSE);
floppy = NULL;
}
if (outoption)
*outoption = err ? -1 : best_option;
if (outfloppy)
*outfloppy = floppy;
return err;
}
floperr_t floppy_identify(void *fp, const struct io_procs *procs, const char *extension,
const struct FloppyFormat *formats, int *identified_format)
{
return floppy_open_internal(fp, procs, extension, formats, INT_MAX, FLOPPY_FLAGS_READONLY, NULL, identified_format);
}
floperr_t floppy_open(void *fp, const struct io_procs *procs, const char *extension,
const struct FloppyFormat *format, int flags, floppy_image **outfloppy)
{
return floppy_open_internal(fp, procs, extension, format, 1, flags, outfloppy, NULL);
}
floperr_t floppy_open_choices(void *fp, const struct io_procs *procs, const char *extension,
const struct FloppyFormat *formats, int flags, floppy_image **outfloppy)
{
return floppy_open_internal(fp, procs, extension, formats, INT_MAX, flags, outfloppy, NULL);
}
static floperr_t option_to_floppy_error(optreserr_t oerr)
{
floperr_t err;
switch(oerr) {
case OPTIONRESOLUTION_ERROR_SUCCESS:
err = FLOPPY_ERROR_SUCCESS;
break;
case OPTIONRESOLUTION_ERROR_OUTOFMEMORY:
err = FLOPPY_ERROR_OUTOFMEMORY;
break;
case OPTIONRESOLUTION_ERROR_PARAMOUTOFRANGE:
case OPTIONRESOLUTION_ERROR_PARAMNOTSPECIFIED:
case OPTIONRESOLUTION_ERROR_PARAMNOTFOUND:
case OPTIONRESOLUTION_ERROR_PARAMALREADYSPECIFIED:
case OPTIONRESOLUTION_ERROR_BADPARAM:
case OPTIONRESOLUTION_ERROR_SYNTAX:
default:
err = FLOPPY_ERROR_INTERNAL;
break;
};
return err;
}
floperr_t floppy_create(void *fp, const struct io_procs *procs, const struct FloppyFormat *format, option_resolution *parameters, floppy_image **outfloppy)
{
floppy_image *floppy = NULL;
optreserr_t oerr;
floperr_t err;
int heads, tracks, h, t;
option_resolution *alloc_resolution = NULL;
assert(format);
/* create the new image */
floppy = floppy_init(fp, procs, 0);
if (!floppy)
{
err = FLOPPY_ERROR_OUTOFMEMORY;
goto done;
}
/* if this format expects creation parameters and none were specified, create some */
if (!parameters && format->param_guidelines)
{
alloc_resolution = option_resolution_create(floppy_option_guide, format->param_guidelines);
if (!alloc_resolution)
{
err = FLOPPY_ERROR_OUTOFMEMORY;
goto done;
}
parameters = alloc_resolution;
}
/* finish the parameters, if specified */
if (parameters)
{
oerr = option_resolution_finish(parameters);
if (oerr)
{
err = option_to_floppy_error(oerr);
goto done;
}
}
/* call the format constructor */
err = format->construct(floppy, format, parameters);
if (err)
goto done;
/* format the disk, ignoring if formatting not implemented */
if (floppy->format.format_track)
{
heads = floppy_get_heads_per_disk(floppy);
tracks = floppy_get_tracks_per_disk(floppy);
for (h = 0; h < heads; h++)
{
for (t = 0; t < tracks; t++)
{
err = floppy->format.format_track(floppy, h, t, parameters);
if (err)
goto done;
}
}
}
/* call the post_format function, if present */
if (floppy->format.post_format)
{
err = floppy->format.post_format(floppy, parameters);
if (err)
goto done;
}
floppy->floppy_option = format;
err = FLOPPY_ERROR_SUCCESS;
done:
if (err && floppy)
{
floppy_close_internal(floppy, FALSE);
floppy = NULL;
}
if (outfloppy)
*outfloppy = floppy;
else if (floppy)
floppy_close_internal(floppy, FALSE);
if (alloc_resolution)
option_resolution_close(alloc_resolution);
return err;
}
static void floppy_close_internal(floppy_image *floppy, int close_file)
{
if (floppy) {
floppy_track_unload(floppy);
if (close_file)
io_generic_close(&floppy->io);
if (floppy->loaded_track_data)
free(floppy->loaded_track_data);
pool_free_lib(floppy->tags);
free(floppy);
}
}
void floppy_close(floppy_image *floppy)
{
floppy_close_internal(floppy, TRUE);
}
/*********************************************************************
functions useful in format constructors
*********************************************************************/
struct FloppyCallbacks *floppy_callbacks(floppy_image *floppy)
{
assert(floppy);
return &floppy->format;
}
void *floppy_tag(floppy_image *floppy)
{
assert(floppy);
return floppy->tag_data;
}
void *floppy_create_tag(floppy_image *floppy, size_t tagsize)
{
floppy->tag_data = pool_malloc_lib(floppy->tags,tagsize);
return floppy->tag_data;
}
UINT8 floppy_get_filler(floppy_image *floppy)
{
return floppy->io.filler;
}
void floppy_set_filler(floppy_image *floppy, UINT8 filler)
{
floppy->io.filler = filler;
}
/*********************************************************************
calls for accessing the raw disk image
*********************************************************************/
void floppy_image_read(floppy_image *floppy, void *buffer, UINT64 offset, size_t length)
{
io_generic_read(&floppy->io, buffer, offset, length);
}
void floppy_image_write(floppy_image *floppy, const void *buffer, UINT64 offset, size_t length)
{
io_generic_write(&floppy->io, buffer, offset, length);
}
void floppy_image_write_filler(floppy_image *floppy, UINT8 filler, UINT64 offset, size_t length)
{
io_generic_write_filler(&floppy->io, filler, offset, length);
}
UINT64 floppy_image_size(floppy_image *floppy)
{
return io_generic_size(&floppy->io);
}
/*********************************************************************
calls for accessing disk image data
*********************************************************************/
static floperr_t floppy_readwrite_sector(floppy_image *floppy, int head, int track, int sector, int offset,
void *buffer, size_t buffer_len, int writing, int indexed, int ddam)
{
floperr_t err;
const struct FloppyCallbacks *fmt;
size_t this_buffer_len;
UINT8 *alloc_buf = NULL;
UINT32 sector_length;
UINT8 *buffer_ptr = (UINT8 *)buffer;
floperr_t (*read_sector)(floppy_image *floppy, int head, int track, int sector, void *buffer, size_t buflen);
floperr_t (*write_sector)(floppy_image *floppy, int head, int track, int sector, const void *buffer, size_t buflen, int ddam);
fmt = floppy_callbacks(floppy);
/* choose proper calls for indexed vs non-indexed */
if (indexed)
{
read_sector = fmt->read_indexed_sector;
write_sector = fmt->write_indexed_sector;
if (!fmt->get_indexed_sector_info)
{
err = FLOPPY_ERROR_UNSUPPORTED;
goto done;
}
}
else
{
read_sector = fmt->read_sector;
write_sector = fmt->write_sector;
if (!fmt->get_sector_length)
{
err = FLOPPY_ERROR_UNSUPPORTED;
goto done;
}
}
/* check to make sure that the operation is supported */
if (!read_sector || (writing && !write_sector))
{
err = FLOPPY_ERROR_UNSUPPORTED;
goto done;
}
/* main loop */
while(buffer_len > 0)
{
/* find out the size of this sector */
if (indexed)
err = fmt->get_indexed_sector_info(floppy, head, track, sector, NULL, NULL, NULL, &sector_length, NULL);
else
err = fmt->get_sector_length(floppy, head, track, sector, &sector_length);
if (err)
goto done;
/* do we even do anything with this sector? */
if (offset < sector_length)
{
/* ok we will be doing something */
if ((offset > 0) || (buffer_len < sector_length))
{
/* we will be doing an partial read/write; in other words we
* will not be reading/writing a full sector */
if (alloc_buf) free(alloc_buf);
alloc_buf = (UINT8*)malloc(sector_length);
if (!alloc_buf)
{
err = FLOPPY_ERROR_OUTOFMEMORY;
goto done;
}
/* read the sector (we need to do this even when writing */
err = read_sector(floppy, head, track, sector, alloc_buf, sector_length);
if (err)
goto done;
this_buffer_len = MIN(buffer_len, sector_length - offset);
if (writing)
{
memcpy(alloc_buf + offset, buffer_ptr, this_buffer_len);
err = write_sector(floppy, head, track, sector, alloc_buf, sector_length, ddam);
if (err)
goto done;
}
else
{
memcpy(buffer_ptr, alloc_buf + offset, this_buffer_len);
}
offset += this_buffer_len;
offset %= sector_length;
}
else
{
this_buffer_len = sector_length;
if (writing)
err = write_sector(floppy, head, track, sector, buffer_ptr, sector_length, ddam);
else
err = read_sector(floppy, head, track, sector, buffer_ptr, sector_length);
if (err)
goto done;
}
}
else
{
/* skip this sector */
offset -= sector_length;
this_buffer_len = 0;
}
buffer_ptr += this_buffer_len;
buffer_len -= this_buffer_len;
sector++;
}
err = FLOPPY_ERROR_SUCCESS;
done:
if (alloc_buf)
free(alloc_buf);
return err;
}
floperr_t floppy_read_sector(floppy_image *floppy, int head, int track, int sector, int offset, void *buffer, size_t buffer_len)
{
return floppy_readwrite_sector(floppy, head, track, sector, offset, buffer, buffer_len, FALSE, FALSE, 0);
}
floperr_t floppy_write_sector(floppy_image *floppy, int head, int track, int sector, int offset, const void *buffer, size_t buffer_len, int ddam)
{
return floppy_readwrite_sector(floppy, head, track, sector, offset, (void *) buffer, buffer_len, TRUE, FALSE, ddam);
}
floperr_t floppy_read_indexed_sector(floppy_image *floppy, int head, int track, int sector_index, int offset, void *buffer, size_t buffer_len)
{
return floppy_readwrite_sector(floppy, head, track, sector_index, offset, buffer, buffer_len, FALSE, TRUE, 0);
}
floperr_t floppy_write_indexed_sector(floppy_image *floppy, int head, int track, int sector_index, int offset, const void *buffer, size_t buffer_len, int ddam)
{
return floppy_readwrite_sector(floppy, head, track, sector_index, offset, (void *) buffer, buffer_len, TRUE, TRUE, ddam);
}
static floperr_t floppy_get_track_data_offset(floppy_image *floppy, int head, int track, UINT64 *offset)
{
floperr_t err;
const struct FloppyCallbacks *callbacks;
*offset = 0;
callbacks = floppy_callbacks(floppy);
if (callbacks->get_track_data_offset)
{
err = callbacks->get_track_data_offset(floppy, head, track, offset);
if (err)
return err;
}
return FLOPPY_ERROR_SUCCESS;
}
static floperr_t floppy_read_track_offset(floppy_image *floppy, int head, int track, UINT64 offset, void *buffer, size_t buffer_len)
{
floperr_t err;
const struct FloppyCallbacks *format;
format = floppy_callbacks(floppy);
if (!format->read_track)
return FLOPPY_ERROR_UNSUPPORTED;
err = floppy_track_unload(floppy);
if (err)
return err;
err = format->read_track(floppy, head, track, offset, buffer, buffer_len);
if (err)
return err;
return FLOPPY_ERROR_SUCCESS;
}
floperr_t floppy_read_track(floppy_image *floppy, int head, int track, void *buffer, size_t buffer_len)
{
return floppy_read_track_offset(floppy, head, track, 0, buffer, buffer_len);
}
floperr_t floppy_read_track_data(floppy_image *floppy, int head, int track, void *buffer, size_t buffer_len)
{
floperr_t err;
UINT64 offset;
err = floppy_get_track_data_offset(floppy, head, track, &offset);
if (err)
return err;
return floppy_read_track_offset(floppy, head, track, offset, buffer, buffer_len);
}
static floperr_t floppy_write_track_offset(floppy_image *floppy, int head, int track, UINT64 offset, const void *buffer, size_t buffer_len)
{
floperr_t err;
/* track writing supported? */
if (!floppy_callbacks(floppy)->write_track)
return FLOPPY_ERROR_UNSUPPORTED;
/* read only? */
if (floppy->flags & FLOPPY_FLAGS_READONLY)
return FLOPPY_ERROR_READONLY;
err = floppy_track_unload(floppy);
if (err)
return err;
err = floppy_callbacks(floppy)->write_track(floppy, head, track, offset, buffer, buffer_len);
if (err)
return err;
return FLOPPY_ERROR_SUCCESS;
}
floperr_t floppy_write_track(floppy_image *floppy, int head, int track, const void *buffer, size_t buffer_len)
{
return floppy_write_track_offset(floppy, head, track, 0, buffer, buffer_len);
}
floperr_t floppy_write_track_data(floppy_image *floppy, int head, int track, const void *buffer, size_t buffer_len)
{
floperr_t err;
UINT64 offset;
err = floppy_get_track_data_offset(floppy, head, track, &offset);
if (err)
return err;
return floppy_write_track_offset(floppy, head, track, offset, buffer, buffer_len);
}
floperr_t floppy_format_track(floppy_image *floppy, int head, int track, option_resolution *parameters)
{
floperr_t err;
struct FloppyCallbacks *format;
option_resolution *alloc_resolution = NULL;
optreserr_t oerr;
/* supported? */
format = floppy_callbacks(floppy);
if (!format->format_track)
{
err = FLOPPY_ERROR_UNSUPPORTED;
goto done;
}
/* create a dummy resolution; if no parameters were specified */
if (!parameters)
{
alloc_resolution = option_resolution_create(floppy_option_guide, floppy->floppy_option->param_guidelines);
if (!alloc_resolution)
{
err = FLOPPY_ERROR_OUTOFMEMORY;
goto done;
}
parameters = alloc_resolution;
}
oerr = option_resolution_finish(parameters);
if (oerr)
{
err = option_to_floppy_error(oerr);
goto done;
}
err = format->format_track(floppy, head, track, parameters);
if (err)
goto done;
done:
if (alloc_resolution)
option_resolution_close(alloc_resolution);
return err;
}
int floppy_get_tracks_per_disk(floppy_image *floppy)
{
return floppy_callbacks(floppy)->get_tracks_per_disk(floppy);
}
int floppy_get_heads_per_disk(floppy_image *floppy)
{
return floppy_callbacks(floppy)->get_heads_per_disk(floppy);
}
UINT32 floppy_get_track_size(floppy_image *floppy, int head, int track)
{
const struct FloppyCallbacks *fmt;
fmt = floppy_callbacks(floppy);
if (!fmt->get_track_size)
return 0;
return fmt->get_track_size(floppy, head, track);
}
floperr_t floppy_get_sector_length(floppy_image *floppy, int head, int track, int sector, UINT32 *sector_length)
{
const struct FloppyCallbacks *fmt;
fmt = floppy_callbacks(floppy);
if (!fmt->get_sector_length)
return FLOPPY_ERROR_UNSUPPORTED;
return fmt->get_sector_length(floppy, head, track, sector, sector_length);
}
floperr_t floppy_get_indexed_sector_info(floppy_image *floppy, int head, int track, int sector_index, int *cylinder, int *side, int *sector, UINT32 *sector_length, unsigned long *flags)
{
const struct FloppyCallbacks *fmt;
fmt = floppy_callbacks(floppy);
if (!fmt->get_indexed_sector_info)
return FLOPPY_ERROR_UNSUPPORTED;
return fmt->get_indexed_sector_info(floppy, head, track, sector_index, cylinder, side, sector, sector_length, flags);
}
floperr_t floppy_get_sector_count(floppy_image *floppy, int head, int track, int *sector_count)
{
floperr_t err;
int sector_index = 0;
do
{
err = floppy_get_indexed_sector_info(floppy, head, track, sector_index, NULL, NULL, NULL, NULL, NULL);
if (!err)
sector_index++;
}
while(!err);
if (sector_index && (err == FLOPPY_ERROR_SEEKERROR))
err = FLOPPY_ERROR_SUCCESS;
if (sector_count)
*sector_count = err ? 0 : sector_index;
return err;
}
int floppy_is_read_only(floppy_image *floppy)
{
return floppy->flags & FLOPPY_FLAGS_READONLY;
}
UINT8 floppy_random_byte(floppy_image *floppy)
{
/* can't use mame_rand(); this might not be in the core */
#ifdef rand
#undef rand
#endif
return rand();
}
/*********************************************************************
calls for track based IO
*********************************************************************/
floperr_t floppy_load_track(floppy_image *floppy, int head, int track, int dirtify, void **track_data, size_t *track_length)
{
floperr_t err;
void *new_loaded_track_data;
UINT32 track_size;
/* have we already loaded this track? */
if (((floppy->loaded_track_status & TRACK_LOADED) == 0) || (head != floppy->loaded_track_head) || (track != floppy->loaded_track_index))
{
err = floppy_track_unload(floppy);
if (err)
goto error;
track_size = floppy_callbacks(floppy)->get_track_size(floppy, head, track);
if (floppy->loaded_track_data) free(floppy->loaded_track_data);
new_loaded_track_data = malloc(track_size);
if (!new_loaded_track_data)
{
err = FLOPPY_ERROR_OUTOFMEMORY;
goto error;
}
floppy->loaded_track_data = new_loaded_track_data;
floppy->loaded_track_size = track_size;
floppy->loaded_track_head = head;
floppy->loaded_track_index = track;
err = floppy_callbacks(floppy)->read_track(floppy, floppy->loaded_track_head, floppy->loaded_track_index, 0, floppy->loaded_track_data, floppy->loaded_track_size);
if (err)
goto error;
floppy->loaded_track_status |= TRACK_LOADED | (dirtify ? TRACK_DIRTY : 0);
}
else
floppy->loaded_track_status |= (dirtify ? TRACK_DIRTY : 0);
if (track_data)
*track_data = floppy->loaded_track_data;
if (track_length)
*track_length = floppy->loaded_track_size;
return FLOPPY_ERROR_SUCCESS;
error:
if (track_data)
*track_data = NULL;
if (track_length)
*track_length = 0;
return err;
}
static floperr_t floppy_track_unload(floppy_image *floppy)
{
int err;
if (floppy->loaded_track_status & TRACK_DIRTY)
{
err = floppy_callbacks(floppy)->write_track(floppy, floppy->loaded_track_head, floppy->loaded_track_index, 0, floppy->loaded_track_data, floppy->loaded_track_size);
if (err)
return (floperr_t)err;
}
floppy->loaded_track_status &= ~(TRACK_LOADED | TRACK_DIRTY);
return FLOPPY_ERROR_SUCCESS;
}
/*********************************************************************
accessors for meta information about the image
*********************************************************************/
const char *floppy_format_description(floppy_image *floppy)
{
return floppy->floppy_option->description;
}
/*********************************************************************
misc calls
*********************************************************************/
const char *floppy_error(floperr_t err)
{
static const char *const error_messages[] =
{
"The operation completed successfully",
"Fatal internal error",
"This operation is unsupported",
"Out of memory",
"Seek error",
"Invalid image",
"Attempted to write to read only image",
"No space left on image",
"Parameter out of range",
"Required parameter not specified"
};
if ((err < 0) || (err >= ARRAY_LENGTH(error_messages)))
return NULL;
return error_messages[err];
}
FLOPPY_OPTIONS_START(default)
FLOPPY_OPTIONS_END

204
src/emu/imagedev/flopimg.h Normal file
View File

@ -0,0 +1,204 @@
/*********************************************************************
flopimg.h
Floppy disk image abstraction code
*********************************************************************/
#ifndef FLOPIMG_H
#define FLOPIMG_H
#include "emu.h"
#include "opresolv.h"
/***************************************************************************
Constants
***************************************************************************/
#define FLOPPY_FLAGS_READWRITE 0
#define FLOPPY_FLAGS_READONLY 1
/***************************************************************************
Type definitions
***************************************************************************/
typedef enum
{
FLOPPY_ERROR_SUCCESS, /* no error */
FLOPPY_ERROR_INTERNAL, /* fatal internal error */
FLOPPY_ERROR_UNSUPPORTED, /* this operation is unsupported */
FLOPPY_ERROR_OUTOFMEMORY, /* ran out of memory */
FLOPPY_ERROR_SEEKERROR, /* attempted to seek to nonexistant location */
FLOPPY_ERROR_INVALIDIMAGE, /* this image in invalid */
FLOPPY_ERROR_READONLY, /* attempt to write to read-only image */
FLOPPY_ERROR_NOSPACE,
FLOPPY_ERROR_PARAMOUTOFRANGE,
FLOPPY_ERROR_PARAMNOTSPECIFIED
}
floperr_t;
typedef struct _floppy_image floppy_image;
struct FloppyCallbacks
{
floperr_t (*read_sector)(floppy_image *floppy, int head, int track, int sector, void *buffer, size_t buflen);
floperr_t (*write_sector)(floppy_image *floppy, int head, int track, int sector, const void *buffer, size_t buflen, int ddam);
floperr_t (*read_indexed_sector)(floppy_image *floppy, int head, int track, int sector_index, void *buffer, size_t buflen);
floperr_t (*write_indexed_sector)(floppy_image *floppy, int head, int track, int sector_index, const void *buffer, size_t buflen, int ddam);
floperr_t (*read_track)(floppy_image *floppy, int head, int track, UINT64 offset, void *buffer, size_t buflen);
floperr_t (*write_track)(floppy_image *floppy, int head, int track, UINT64 offset, const void *buffer, size_t buflen);
floperr_t (*format_track)(floppy_image *floppy, int head, int track, option_resolution *params);
floperr_t (*post_format)(floppy_image *floppy, option_resolution *params);
int (*get_heads_per_disk)(floppy_image *floppy);
int (*get_tracks_per_disk)(floppy_image *floppy);
int (*get_sectors_per_track)(floppy_image *floppy, int head, int track);
UINT32 (*get_track_size)(floppy_image *floppy, int head, int track);
floperr_t (*get_sector_length)(floppy_image *floppy, int head, int track, int sector, UINT32 *sector_length);
floperr_t (*get_indexed_sector_info)(floppy_image *floppy, int head, int track, int sector_index, int *cylinder, int *side, int *sector, UINT32 *sector_length, unsigned long *flags);
floperr_t (*get_track_data_offset)(floppy_image *floppy, int head, int track, UINT64 *offset);
};
struct FloppyFormat
{
const char *name;
const char *extensions;
const char *description;
floperr_t (*identify)(floppy_image *floppy, const struct FloppyFormat *format, int *vote);
floperr_t (*construct)(floppy_image *floppy, const struct FloppyFormat *format, option_resolution *params);
const char *param_guidelines;
};
#define FLOPPY_IDENTIFY(name) floperr_t name(floppy_image *floppy, const struct FloppyFormat *format, int *vote)
#define FLOPPY_CONSTRUCT(name) floperr_t name(floppy_image *floppy, const struct FloppyFormat *format, option_resolution *params)
FLOPPY_IDENTIFY(td0_dsk_identify);
FLOPPY_CONSTRUCT(td0_dsk_construct);
FLOPPY_IDENTIFY(imd_dsk_identify);
FLOPPY_CONSTRUCT(imd_dsk_construct);
FLOPPY_IDENTIFY(cqm_dsk_identify);
FLOPPY_CONSTRUCT(cqm_dsk_construct);
FLOPPY_IDENTIFY(dsk_dsk_identify);
FLOPPY_CONSTRUCT(dsk_dsk_construct);
FLOPPY_IDENTIFY(d88_dsk_identify);
FLOPPY_CONSTRUCT(d88_dsk_construct);
FLOPPY_IDENTIFY(fdi_dsk_identify);
FLOPPY_CONSTRUCT(fdi_dsk_construct);
#define FLOPPY_OPTIONS_NAME(name) floppyoptions_##name
#define FLOPPY_OPTIONS_START(name) \
const struct FloppyFormat floppyoptions_##name[] = \
{ \
#define FLOPPY_OPTIONS_END0 \
{ NULL } \
};
#define FLOPPY_OPTIONS_EXTERN(name) \
extern const struct FloppyFormat floppyoptions_##name[] \
#define FLOPPY_OPTION(name, extensions_, description_, identify_, construct_, ranges_)\
{ #name, extensions_, description_, identify_, construct_, ranges_ }, \
#define FLOPPY_OPTIONS_END \
FLOPPY_OPTION( fdi, "fdi", "Formatted Disk Image", fdi_dsk_identify, fdi_dsk_construct, NULL) \
FLOPPY_OPTION( td0, "td0", "Teledisk floppy disk image", td0_dsk_identify, td0_dsk_construct, NULL) \
FLOPPY_OPTION( imd, "imd", "IMD floppy disk image", imd_dsk_identify, imd_dsk_construct, NULL) \
FLOPPY_OPTION( cqm, "cqm,dsk", "CopyQM floppy disk image", cqm_dsk_identify, cqm_dsk_construct, NULL) \
FLOPPY_OPTION( dsk, "dsk", "DSK floppy disk image", dsk_dsk_identify, dsk_dsk_construct, NULL) \
FLOPPY_OPTION( d88, "d77,d88,1dd", "D88 Floppy Disk image", d88_dsk_identify, d88_dsk_construct, NULL) \
FLOPPY_OPTIONS_END0
FLOPPY_OPTIONS_EXTERN(default);
#define PARAM_END '\0'
#define PARAM_HEADS 'H'
#define PARAM_TRACKS 'T'
#define PARAM_SECTORS 'S'
#define PARAM_SECTOR_LENGTH 'L'
#define PARAM_INTERLEAVE 'I'
#define PARAM_FIRST_SECTOR_ID 'F'
#define HEADS(range) "H" #range
#define TRACKS(range) "T" #range
#define SECTORS(range) "S" #range
#define SECTOR_LENGTH(range) "L" #range
#define INTERLEAVE(range) "I" #range
#define FIRST_SECTOR_ID(range) "F" #range
/***************************************************************************
Prototypes
***************************************************************************/
OPTION_GUIDE_EXTERN(floppy_option_guide);
/* opening, closing and creating of floppy images */
floperr_t floppy_open(void *fp, const struct io_procs *procs, const char *extension, const struct FloppyFormat *format, int flags, floppy_image **outfloppy);
floperr_t floppy_open_choices(void *fp, const struct io_procs *procs, const char *extension, const struct FloppyFormat *formats, int flags, floppy_image **outfloppy);
floperr_t floppy_create(void *fp, const struct io_procs *procs, const struct FloppyFormat *format, option_resolution *parameters, floppy_image **outfloppy);
void floppy_close(floppy_image *floppy);
/* useful for identifying a floppy image */
floperr_t floppy_identify(void *fp, const struct io_procs *procs, const char *extension,
const struct FloppyFormat *formats, int *identified_format);
/* functions useful within format constructors */
void *floppy_tag(floppy_image *floppy);
void *floppy_create_tag(floppy_image *floppy, size_t tagsize);
struct FloppyCallbacks *floppy_callbacks(floppy_image *floppy);
UINT8 floppy_get_filler(floppy_image *floppy);
void floppy_set_filler(floppy_image *floppy, UINT8 filler);
/* calls for accessing disk image data */
floperr_t floppy_read_sector(floppy_image *floppy, int head, int track, int sector, int offset, void *buffer, size_t buffer_len);
floperr_t floppy_write_sector(floppy_image *floppy, int head, int track, int sector, int offset, const void *buffer, size_t buffer_len, int ddam);
floperr_t floppy_read_indexed_sector(floppy_image *floppy, int head, int track, int sector_index, int offset, void *buffer, size_t buffer_len);
floperr_t floppy_write_indexed_sector(floppy_image *floppy, int head, int track, int sector_index, int offset, const void *buffer, size_t buffer_len, int ddam);
floperr_t floppy_read_track(floppy_image *floppy, int head, int track, void *buffer, size_t buffer_len);
floperr_t floppy_write_track(floppy_image *floppy, int head, int track, const void *buffer, size_t buffer_len);
floperr_t floppy_read_track_data(floppy_image *floppy, int head, int track, void *buffer, size_t buffer_len);
floperr_t floppy_write_track_data(floppy_image *floppy, int head, int track, const void *buffer, size_t buffer_len);
floperr_t floppy_format_track(floppy_image *floppy, int head, int track, option_resolution *params);
int floppy_get_tracks_per_disk(floppy_image *floppy);
int floppy_get_heads_per_disk(floppy_image *floppy);
UINT32 floppy_get_track_size(floppy_image *floppy, int head, int track);
floperr_t floppy_get_sector_length(floppy_image *floppy, int head, int track, int sector, UINT32 *sector_length);
floperr_t floppy_get_indexed_sector_info(floppy_image *floppy, int head, int track, int sector_index, int *cylinder, int *side, int *sector, UINT32 *sector_length, unsigned long *flags);
floperr_t floppy_get_sector_count(floppy_image *floppy, int head, int track, int *sector_count);
floperr_t floppy_load_track(floppy_image *floppy, int head, int track, int dirtify, void **track_data, size_t *track_length);
int floppy_is_read_only(floppy_image *floppy);
UINT8 floppy_random_byte(floppy_image *floppy);
/* accessors for meta information about the image */
const char *floppy_format_description(floppy_image *floppy);
/* calls for accessing the raw disk image */
void floppy_image_read(floppy_image *floppy, void *buffer, UINT64 offset, size_t length);
void floppy_image_write(floppy_image *floppy, const void *buffer, UINT64 offset, size_t length);
void floppy_image_write_filler(floppy_image *floppy, UINT8 filler, UINT64 offset, size_t length);
UINT64 floppy_image_size(floppy_image *floppy);
/* misc */
const char *floppy_error(floperr_t err);
#endif /* FLOPIMG_H */

404
src/emu/imagedev/harddriv.c Normal file
View File

@ -0,0 +1,404 @@
/*********************************************************************
Code to interface the MESS image code with MAME's harddisk core.
We do not support diff files as it will involve some changes in
the MESS image code. Additionally, the need for diff files comes
from MAME's need for "cannonical" hard drive images.
Raphael Nabet 2003
Update: 23-Feb-2004 - Unlike floppy disks, for which we support
myriad formats on many systems, it is my intention for MESS to
standardize on the CHD file format for hard drives so I made a few
changes to support this
*********************************************************************/
#include "emu.h"
#include "harddisk.h"
#include "harddriv.h"
static const char *const error_strings[] =
{
"no error",
"no drive interface",
"out of memory",
"invalid file",
"invalid parameter",
"invalid data",
"file not found",
"requires parent",
"file not writeable",
"read error",
"write error",
"codec error",
"invalid parent",
"hunk out of range",
"decompression error",
"compression error",
"can't create file",
"can't verify file"
"operation not supported",
"can't find metadata",
"invalid metadata size",
"unsupported CHD version"
};
static const char *chd_get_error_string(int chderr)
{
if ((chderr < 0 ) || (chderr >= ARRAY_LENGTH(error_strings)))
return NULL;
return error_strings[chderr];
}
static OPTION_GUIDE_START(mess_hd_option_guide)
OPTION_INT('C', "cylinders", "Cylinders")
OPTION_INT('H', "heads", "Heads")
OPTION_INT('S', "sectors", "Sectors")
OPTION_INT('L', "sectorlength", "Sector Bytes")
OPTION_INT('K', "hunksize", "Hunk Bytes")
OPTION_GUIDE_END
static const char *mess_hd_option_spec =
"C1-[512]-1024;H1/2/[4]/8;S1-[16]-64;L128/256/[512]/1024;K512/1024/2048/[4096]";
typedef struct _dev_harddisk_t dev_harddisk_t;
struct _dev_harddisk_t
{
const struct harddisk_callback_config *config;
chd_file *chd;
hard_disk_file *hard_disk_handle;
};
INLINE dev_harddisk_t *get_safe_token(device_t *device)
{
assert( device != NULL );
assert( ( device->type() == HARDDISK ) ||
( device->type() == IDE_HARDDISK ) );
return (dev_harddisk_t *) downcast<legacy_device_base *>(device)->token();
}
/*************************************
*
* DEVICE_IMAGE_LOAD(mess_hd)
* DEVICE_IMAGE_CREATE(mess_hd)
*
* Device load and create
*
*************************************/
static int internal_load_mess_hd(device_image_interface &image, const char *metadata)
{
dev_harddisk_t *harddisk = get_safe_token( &image.device() );
chd_error err = (chd_error)0;
int is_writeable;
/* open the CHD file */
do
{
is_writeable = image.is_writable();
harddisk->chd = NULL;
err = chd_open_file(image.image_core_file(), is_writeable ? CHD_OPEN_READWRITE : CHD_OPEN_READ, NULL, &harddisk->chd);
/* special case; if we get CHDERR_FILE_NOT_WRITEABLE, make the
* image read only and repeat */
if (err == CHDERR_FILE_NOT_WRITEABLE)
image.make_readonly();
}
while(!harddisk->chd && is_writeable && (err == CHDERR_FILE_NOT_WRITEABLE));
if (!harddisk->chd)
goto done;
/* if we created the image and hence, have metadata to set, set the metadata */
if (metadata)
{
err = chd_set_metadata(harddisk->chd, HARD_DISK_METADATA_TAG, 0, metadata, strlen(metadata) + 1, 0);
if (err != CHDERR_NONE)
goto done;
}
/* open the hard disk file */
harddisk->hard_disk_handle = hard_disk_open(harddisk->chd);
if (!harddisk->hard_disk_handle)
goto done;
done:
if (err)
{
/* if we had an error, close out the CHD */
if (harddisk->chd != NULL)
{
chd_close(harddisk->chd);
harddisk->chd = NULL;
}
image.seterror(IMAGE_ERROR_UNSPECIFIED, chd_get_error_string(err));
}
return err ? IMAGE_INIT_FAIL : IMAGE_INIT_PASS;
}
static DEVICE_IMAGE_LOAD( mess_hd )
{
dev_harddisk_t *harddisk = get_safe_token( image );
int our_result;
our_result = internal_load_mess_hd(image, NULL);
/* Check if there is an image_load callback defined */
if ( harddisk->config && harddisk->config->device_image_load )
{
/* Let the override do some additional work/checks */
our_result = harddisk->config->device_image_load( image );
}
return our_result;
}
static DEVICE_IMAGE_CREATE( mess_hd )
{
int err;
char metadata[256];
UINT32 sectorsize, hunksize;
UINT32 cylinders, heads, sectors, totalsectors;
cylinders = option_resolution_lookup_int(create_args, 'C');
heads = option_resolution_lookup_int(create_args, 'H');
sectors = option_resolution_lookup_int(create_args, 'S');
sectorsize = option_resolution_lookup_int(create_args, 'L');
hunksize = option_resolution_lookup_int(create_args, 'K');
totalsectors = cylinders * heads * sectors;
/* create the CHD file */
err = chd_create_file(image.image_core_file(), (UINT64)totalsectors * (UINT64)sectorsize, hunksize, CHDCOMPRESSION_NONE, NULL);
if (err != CHDERR_NONE)
goto error;
sprintf(metadata, HARD_DISK_METADATA_FORMAT, cylinders, heads, sectors, sectorsize);
return internal_load_mess_hd(image, metadata);
error:
return IMAGE_INIT_FAIL;
}
/*************************************
*
* DEVICE_IMAGE_UNLOAD(mess_hd)
*
* Device unload
*
*************************************/
static DEVICE_IMAGE_UNLOAD( mess_hd )
{
dev_harddisk_t *harddisk = get_safe_token( image );
/* Check if there is an image_unload callback defined */
if ( harddisk->config && harddisk->config->device_image_unload )
{
harddisk->config->device_image_unload( image );
}
if (harddisk->hard_disk_handle != NULL)
{
hard_disk_close(harddisk->hard_disk_handle);
harddisk->hard_disk_handle = NULL;
}
if (harddisk->chd != NULL)
{
chd_close(harddisk->chd);
harddisk->chd = NULL;
}
}
/*************************************
*
* Get the MESS/MAME hard disk handle (from the src/harddisk.c core)
* after an image has been opened with the mess_hd core
*
*************************************/
hard_disk_file *mess_hd_get_hard_disk_file(device_t *device)
{
dev_harddisk_t *harddisk = get_safe_token( device );
return harddisk->hard_disk_handle;
}
/*************************************
*
* Get the MESS/MAME CHD file (from the src/chd.c core)
* after an image has been opened with the mess_hd core
*
*************************************/
chd_file *mess_hd_get_chd_file(device_t *device)
{
chd_file *result = NULL;
hard_disk_file *hd_file;
if (device)
{
hd_file = mess_hd_get_hard_disk_file(device);
if (hd_file)
result = hard_disk_get_chd(hd_file);
}
return result;
}
/*-------------------------------------------------
DEVICE_START(mess_hd)
-------------------------------------------------*/
static DEVICE_START(mess_hd)
{
dev_harddisk_t *harddisk = get_safe_token( device );
harddisk->config = (const harddisk_callback_config*)device->baseconfig().static_config();
harddisk->chd = NULL;
harddisk->hard_disk_handle = NULL;
}
/*-------------------------------------------------
DEVICE_GET_INFO(mess_hd)
-------------------------------------------------*/
DEVICE_GET_INFO(mess_hd)
{
switch( state )
{
/* --- the following bits of info are returned as 64-bit signed integers --- */
case DEVINFO_INT_TOKEN_BYTES: info->i = sizeof(dev_harddisk_t); break;
case DEVINFO_INT_INLINE_CONFIG_BYTES: info->i = 0; break;
case DEVINFO_INT_IMAGE_TYPE: info->i = IO_HARDDISK; break;
case DEVINFO_INT_IMAGE_READABLE: info->i = 1; break;
case DEVINFO_INT_IMAGE_WRITEABLE: info->i = 1; break;
case DEVINFO_INT_IMAGE_CREATABLE: info->i = 0; break;
case DEVINFO_INT_IMAGE_CREATE_OPTCOUNT: info->i = 1; break;
/* --- the following bits of info are returned as pointers to data or functions --- */
case DEVINFO_FCT_START: info->start = DEVICE_START_NAME(mess_hd); break;
case DEVINFO_FCT_IMAGE_LOAD: info->f = (genf *) DEVICE_IMAGE_LOAD_NAME(mess_hd); break;
case DEVINFO_FCT_IMAGE_UNLOAD: info->f = (genf *) DEVICE_IMAGE_UNLOAD_NAME(mess_hd); break;
case DEVINFO_FCT_IMAGE_CREATE: info->f = (genf *) DEVICE_IMAGE_CREATE_NAME(mess_hd); break;
case DEVINFO_PTR_IMAGE_CREATE_OPTGUIDE: info->p = (void *) mess_hd_option_guide; break;
case DEVINFO_PTR_IMAGE_CREATE_OPTSPEC+0: info->p = (void *) mess_hd_option_spec; break;
/* --- the following bits of info are returned as NULL-terminated strings --- */
case DEVINFO_STR_NAME: strcpy(info->s, "Harddisk"); break;
case DEVINFO_STR_FAMILY: strcpy(info->s, "Harddisk"); break;
case DEVINFO_STR_SOURCE_FILE: strcpy(info->s, __FILE__); break;
case DEVINFO_STR_IMAGE_FILE_EXTENSIONS: strcpy(info->s, "chd,hd"); break;
case DEVINFO_STR_IMAGE_CREATE_OPTNAME+0: strcpy(info->s, "chd"); break;
case DEVINFO_STR_IMAGE_CREATE_OPTDESC+0: strcpy(info->s, "MAME/MESS CHD Hard drive"); break;
case DEVINFO_STR_IMAGE_CREATE_OPTEXTS+0: strcpy(info->s, "chd,hd"); break;
}
}
static DEVICE_START(mess_ide)
{
/* old code from idedrive.c */
#ifdef UNUSED_FUNCTION
int which_bus, which_address;
struct ide_interface *intf;
device_start_func parent_init;
/* get the basics */
ide_get_params(device, &which_bus, &which_address, &intf, &parent_init, NULL, NULL);
/* call the parent init function */
parent_init(device);
/* configure IDE */
/* FIXME IDE */
/* ide_controller_init_custom(which_bus, intf, NULL); */
#endif
}
static DEVICE_IMAGE_LOAD(mess_ide)
{
/* old code from idedrive.c */
#ifdef UNUSED_FUNCTION
int result, which_bus, which_address;
struct ide_interface *intf;
device_image_load_func parent_load;
/* get the basics */
ide_get_params(image, &which_bus, &which_address, &intf, NULL, &parent_load, NULL);
/* call the parent load function */
result = parent_load(image);
if (result != IMAGE_INIT_PASS)
return result;
/* configure IDE */
/* FIXME IDE */
/* ide_controller_init_custom(which_bus, intf, mess_hd_get_chd_file(image)); */
/* ide_controller_reset(which_bus); */
return IMAGE_INIT_PASS;
#endif
return device_load_mess_hd( image );
}
static DEVICE_IMAGE_UNLOAD(mess_ide)
{
/* old code from idedrive.c */
#ifdef UNUSED_FUNCTION
int which_bus, which_address;
struct ide_interface *intf;
device_image_unload_func parent_unload;
/* get the basics */
ide_get_params(image, &which_bus, &which_address, &intf, NULL, NULL, &parent_unload);
/* call the parent unload function */
parent_unload(image);
/* configure IDE */
/* FIXME IDE */
/* ide_controller_init_custom(which_bus, intf, NULL); */
/* ide_controller_reset(which_bus); */
#endif
device_unload_mess_hd( image );
}
DEVICE_GET_INFO(mess_ide)
{
switch( state )
{
/* --- the following bits of info are returned as pointers to data or functions --- */
case DEVINFO_FCT_START: info->start = DEVICE_START_NAME(mess_ide); break;
case DEVINFO_FCT_IMAGE_LOAD: info->f = (genf *) DEVICE_IMAGE_LOAD_NAME(mess_ide); break;
case DEVINFO_FCT_IMAGE_UNLOAD: info->f = (genf *) DEVICE_IMAGE_UNLOAD_NAME(mess_ide); break;
/* --- the following bits of info are returned as NULL-terminated strings --- */
case DEVINFO_STR_NAME: strcpy(info->s, "IDE harddisk"); break;
case DEVINFO_STR_IMAGE_INSTANCE_NAME: strcpy(info->s, "ideharddrive"); break;
case DEVINFO_STR_IMAGE_BRIEF_INSTANCE_NAME: strcpy(info->s, "idehd"); break;
default: DEVICE_GET_INFO_CALL( mess_hd ); break;
}
}
DEFINE_LEGACY_IMAGE_DEVICE(HARDDISK, mess_hd);
DEFINE_LEGACY_IMAGE_DEVICE(IDE_HARDDISK, mess_ide);

View File

@ -0,0 +1,34 @@
/*********************************************************************
harddriv.h
MESS interface to the MAME CHD code
*********************************************************************/
#ifndef MESS_HD_H
#define MESS_HD_H
#include "image.h"
#include "harddisk.h"
DECLARE_LEGACY_IMAGE_DEVICE(HARDDISK, mess_hd);
DECLARE_LEGACY_IMAGE_DEVICE(IDE_HARDDISK, mess_ide);
#define MCFG_HARDDISK_ADD(_tag) \
MCFG_DEVICE_ADD(_tag, HARDDISK, 0) \
#define MCFG_IDE_HARDDISK_ADD(_tag) \
MCFG_DEVICE_ADD(_tag, IDE_HARDDISK, 0) \
hard_disk_file *mess_hd_get_hard_disk_file(device_t *device);
chd_file *mess_hd_get_chd_file(device_t *device);
struct harddisk_callback_config
{
device_image_load_func device_image_load;
device_image_unload_func device_image_unload;
};
#endif /* MESS_HD_H */

607
src/emu/imagedev/multcart.c Normal file
View File

@ -0,0 +1,607 @@
/*********************************************************************
multcart.c
Multi-cartridge handling code
*********************************************************************/
#include "multcart.h"
#include "pool.h"
#include "unzip.h"
#include "corestr.h"
#include "xmlfile.h"
#include "emu.h"
#include "hash.h"
#include "machine/ram.h"
/***************************************************************************
TYPE DEFINITIONS
***************************************************************************/
struct _multicart_private
{
object_pool * pool;
zip_file * zip;
};
typedef struct _multicart_load_state multicart_load_state;
struct _multicart_load_state
{
multicart_t * multicart;
zip_file * zip;
xml_data_node * layout_xml;
xml_data_node * resources_node;
xml_data_node * pcb_node;
multicart_resource * resources;
multicart_socket * sockets;
};
static const char error_text[14][30] =
{
"no error",
"not a multicart",
"module definition corrupt",
"out of memory",
"xml format error",
"invalid file reference",
"zip file error",
"missing ram length",
"invalid ram specification",
"unknown resource type",
"invalid resource reference",
"invalid file format",
"missing layout",
"no pcb or resource found"
};
const char *multicart_error_text(multicart_open_error error)
{
return error_text[(int)error];
}
/***************************************************************************
IMPLEMENTATION
***************************************************************************/
/*-------------------------------------------------
find_file
-------------------------------------------------*/
static const zip_file_header *find_file(zip_file *zip, const char *filename)
{
const zip_file_header *header;
for (header = zip_file_first_file(zip); header != NULL; header = zip_file_next_file(zip))
{
if (!core_stricmp(header->filename, filename))
return header;
}
return NULL;
}
static const zip_file_header *find_file_crc(zip_file *zip, const char *filename, UINT32 crc)
{
const zip_file_header *header;
for (header = zip_file_first_file(zip); header != NULL; header = zip_file_next_file(zip))
{
// if the CRC and name both match, we're good
// if the CRC matches and the name doesn't, we're still good
if ((!core_stricmp(header->filename, filename)) && (header->crc == crc))
{
return header;
}
else if (header->crc == crc)
{
return header;
}
}
return NULL;
}
/*-------------------------------------------------
find_pcb_and_resource_nodes
-------------------------------------------------*/
static int find_pcb_and_resource_nodes(xml_data_node *layout_xml,
xml_data_node **pcb_node, xml_data_node **resource_node)
{
xml_data_node *romset_node;
xml_data_node *configuration_node;
*pcb_node = NULL;
*resource_node = NULL;
romset_node = xml_get_sibling(layout_xml->child, "romset");
if (romset_node == NULL)
return FALSE;
configuration_node = xml_get_sibling(romset_node->child, "configuration");
if (configuration_node == NULL)
return FALSE;
*pcb_node = xml_get_sibling(configuration_node->child, "pcb");
if (*pcb_node == NULL)
return FALSE;
*resource_node = xml_get_sibling(romset_node->child, "resources");
if (*resource_node == NULL)
return FALSE;
return TRUE;
}
/*-------------------------------------------------
get_resource_type
-------------------------------------------------*/
static multicart_resource_type get_resource_type(const char *s)
{
multicart_resource_type result;
if (!strcmp(s, "rom"))
result = MULTICART_RESOURCE_TYPE_ROM;
else if (!strcmp(s, "ram"))
result = MULTICART_RESOURCE_TYPE_RAM;
else
result = MULTICART_RESOURCE_TYPE_INVALID;
return result;
}
/*-------------------------------------------------
load_rom_resource
-------------------------------------------------*/
static multicart_open_error load_rom_resource(multicart_load_state *state, xml_data_node *resource_node,
multicart_resource *resource)
{
const char *file, *crcstr, *sha1;
const zip_file_header *header;
zip_error ziperr;
UINT32 crc;
/* locate the 'file' attribute */
file = xml_get_attribute_string(resource_node, "file", NULL);
if (file == NULL)
return MCERR_XML_ERROR;
if (!(crcstr = xml_get_attribute_string(resource_node, "crc", NULL)))
{
/* locate the file in the ZIP file */
header = find_file(state->zip, file);
}
else /* CRC tag is present, use it */
{
crc = strtoul(crcstr, NULL, 16);
header = find_file_crc(state->zip, file, crc);
}
if (header == NULL)
return MCERR_INVALID_FILE_REF;
resource->length = header->uncompressed_length;
/* allocate bytes for this resource */
resource->ptr = pool_malloc_lib(state->multicart->data->pool, resource->length);
if (resource->ptr == NULL)
return MCERR_OUT_OF_MEMORY;
/* and decompress it */
ziperr = zip_file_decompress(state->zip, resource->ptr, resource->length);
if (ziperr != ZIPERR_NONE)
return MCERR_ZIP_ERROR;
/* check SHA1 now */
if ((sha1 = xml_get_attribute_string(resource_node, "sha1", NULL)))
{
char calc_sha[256];
memset(calc_sha, 0, sizeof(calc_sha));
hash_compute(&calc_sha[0], (const unsigned char*)resource->ptr, resource->length, HASH_SHA1);
if ((strncmp(sha1, &calc_sha[2], 20)))
{
return MCERR_INVALID_FILE_REF;
}
}
return MCERR_NONE;
}
/*-------------------------------------------------
load_ram_resource
-------------------------------------------------*/
static multicart_open_error load_ram_resource(multicart_load_state *state, xml_data_node *resource_node,
multicart_resource *resource)
{
const char *length_string;
const char *ram_type;
const char *ram_filename;
astring *ram_pathname;
/* locate the 'length' attribute */
length_string = xml_get_attribute_string(resource_node, "length", NULL);
if (length_string == NULL)
return MCERR_MISSING_RAM_LENGTH;
/* ...and parse it */
resource->length = ram_parse_string(length_string);
if (resource->length <= 0)
return MCERR_INVALID_RAM_SPEC;
/* allocate bytes for this resource */
resource->ptr = pool_malloc_lib(state->multicart->data->pool, resource->length);
if (resource->ptr == NULL)
return MCERR_OUT_OF_MEMORY;
/* Is this a persistent RAM resource? Then try to load it. */
ram_type = xml_get_attribute_string(resource_node, "type", NULL);
if (ram_type != NULL)
{
if (strcmp(ram_type, "persistent")==0)
{
astring tmp;
/* Get the file name. */
ram_filename = xml_get_attribute_string(resource_node, "file", NULL);
if (ram_filename==NULL)
return MCERR_XML_ERROR;
ram_pathname = astring_assemble_3(&tmp, state->multicart->gamedrv_name, PATH_SEPARATOR, ram_filename);
/* Save the file name so that we can write the contents on unloading.
If the RAM resource has no filename, we know that it was volatile only. */
resource->filename = pool_strdup_lib(state->multicart->data->pool, astring_c(ram_pathname));
if (resource->filename == NULL)
return MCERR_OUT_OF_MEMORY;
image_battery_load_by_name(resource->filename, resource->ptr, resource->length, 0x00);
}
/* else this type is volatile, in which case we just have
a memory expansion */
}
return MCERR_NONE;
}
/*-------------------------------------------------
load_resource
-------------------------------------------------*/
static multicart_open_error load_resource(multicart_load_state *state, xml_data_node *resource_node,
multicart_resource_type resource_type)
{
const char *id;
multicart_open_error err;
multicart_resource *resource;
multicart_resource **next_resource;
/* get the 'id' attribute; error if not present */
id = xml_get_attribute_string(resource_node, "id", NULL);
if (id == NULL)
return MCERR_XML_ERROR;
/* allocate memory for the resource */
resource = (multicart_resource *)pool_malloc_lib(state->multicart->data->pool, sizeof(*resource));
if (resource == NULL)
return MCERR_OUT_OF_MEMORY;
memset(resource, 0, sizeof(*resource));
resource->type = resource_type;
/* copy id */
resource->id = pool_strdup_lib(state->multicart->data->pool, id);
if (resource->id == NULL)
return MCERR_OUT_OF_MEMORY;
switch(resource->type)
{
case MULTICART_RESOURCE_TYPE_ROM:
err = load_rom_resource(state, resource_node, resource);
if (err != MCERR_NONE)
return err;
break;
case MULTICART_RESOURCE_TYPE_RAM:
err = load_ram_resource(state, resource_node, resource);
if (err != MCERR_NONE)
return err;
break;
default:
return MCERR_UNKNOWN_RESOURCE_TYPE;
}
/* append the resource */
for (next_resource = &state->resources; *next_resource; next_resource = &(*next_resource)->next)
;
*next_resource = resource;
return MCERR_NONE;
}
/*-------------------------------------------------
load_all_resources
-------------------------------------------------*/
static multicart_open_error load_all_resources(multicart_load_state *state)
{
multicart_open_error err;
xml_data_node *resource_node;
multicart_resource_type resource_type;
for (resource_node = state->resources_node->child; resource_node != NULL; resource_node = resource_node->next)
{
resource_type = get_resource_type(resource_node->name);
if (resource_type != MULTICART_RESOURCE_TYPE_INVALID)
{
err = load_resource(state, resource_node, resource_type);
if (err != MCERR_NONE)
return err;
}
}
state->multicart->resources = state->resources;
return MCERR_NONE;
}
/*-------------------------------------------------
save_ram_resources. This is important for persistent RAM. All
resources were allocated within the memory pool of this device and will
be freed on multicart_close.
-------------------------------------------------*/
static multicart_open_error save_ram_resources(multicart_t *cart)
{
const multicart_resource *resource;
for (resource = cart->resources; resource != NULL; resource = resource->next)
{
if ((resource->type == MULTICART_RESOURCE_TYPE_RAM) && (resource->filename != NULL))
{
image_battery_save_by_name(resource->filename, resource->ptr, resource->length);
}
}
return MCERR_NONE;
}
/*-------------------------------------------------
load_socket
-------------------------------------------------*/
static multicart_open_error load_socket(multicart_load_state *state, xml_data_node *socket_node)
{
const char *id;
const char *uses;
const multicart_resource *resource;
multicart_socket *socket;
multicart_socket **next_socket;
/* get the 'id' and 'uses' attributes; error if not present */
id = xml_get_attribute_string(socket_node, "id", NULL);
uses = xml_get_attribute_string(socket_node, "uses", NULL);
if ((id == NULL) || (uses == NULL))
return MCERR_XML_ERROR;
/* find the resource */
for (resource = state->multicart->resources; resource != NULL; resource = resource->next)
{
if (!strcmp(uses, resource->id))
break;
}
if (resource == NULL)
return MCERR_INVALID_RESOURCE_REF;
/* create the socket */
socket = (multicart_socket *)pool_malloc_lib(state->multicart->data->pool, sizeof(*socket));
if (socket == NULL)
return MCERR_OUT_OF_MEMORY;
memset(socket, 0, sizeof(*socket));
socket->resource = resource;
socket->ptr = resource->ptr;
/* copy id */
socket->id = pool_strdup_lib(state->multicart->data->pool, id);
if (socket->id == NULL)
return MCERR_OUT_OF_MEMORY;
/* which pointer should I use? */
if (resource->ptr != NULL)
{
/* use the resource's ptr */
socket->ptr = resource->ptr;
}
else
{
/* allocate bytes for this socket */
socket->ptr = pool_malloc_lib(state->multicart->data->pool, resource->length);
if (socket->ptr == NULL)
return MCERR_OUT_OF_MEMORY;
/* ...and clear it */
memset(socket->ptr, 0xCD, resource->length);
}
/* append the resource */
for (next_socket = &state->sockets; *next_socket; next_socket = &(*next_socket)->next)
;
*next_socket = socket;
return MCERR_NONE;
}
/*-------------------------------------------------
load_all_sockets
-------------------------------------------------*/
static multicart_open_error load_all_sockets(multicart_load_state *state)
{
multicart_open_error err;
xml_data_node *socket_node;
for (socket_node = xml_get_sibling(state->pcb_node->child, "socket"); socket_node != NULL;
socket_node = xml_get_sibling(socket_node->next, "socket"))
{
err = load_socket(state, socket_node);
if (err != MCERR_NONE)
return err;
}
state->multicart->sockets = state->sockets;
return MCERR_NONE;
}
/*-------------------------------------------------
multicart_open - opens a multicart
-------------------------------------------------*/
multicart_open_error multicart_open(const char *filename, const char *gamedrv, multicart_load_flags load_flags, multicart_t **cart)
{
multicart_open_error err;
zip_error ziperr;
object_pool *pool;
multicart_load_state state = {0, };
const zip_file_header *header;
const char *pcb_type;
char *layout_text = NULL;
/* allocate an object pool */
pool = pool_alloc_lib(NULL);
if (pool == NULL)
{
err = MCERR_OUT_OF_MEMORY;
goto done;
}
/* allocate the multicart */
state.multicart = (multicart_t*)pool_malloc_lib(pool, sizeof(*state.multicart));
if (state.multicart == NULL)
{
err = MCERR_OUT_OF_MEMORY;
goto done;
}
memset(state.multicart, 0, sizeof(*state.multicart));
/* allocate the multicart's private data */
state.multicart->data = (multicart_private*)pool_malloc_lib(pool, sizeof(*state.multicart->data));
if (state.multicart->data == NULL)
{
err = MCERR_OUT_OF_MEMORY;
goto done;
}
memset(state.multicart->data, 0, sizeof(*state.multicart->data));
state.multicart->data->pool = pool;
pool = NULL;
/* open the ZIP file */
ziperr = zip_file_open(filename, &state.zip);
if (ziperr != ZIPERR_NONE)
{
err = MCERR_NOT_MULTICART;
goto done;
}
/* find the layout.xml file */
header = find_file(state.zip, "layout.xml");
if (header == NULL)
{
err = MCERR_MISSING_LAYOUT;
goto done;
}
/* reserve space for the layout text */
layout_text = (char*)malloc(header->uncompressed_length + 1);
if (layout_text == NULL)
{
err = MCERR_OUT_OF_MEMORY;
goto done;
}
/* uncompress the layout text */
ziperr = zip_file_decompress(state.zip, layout_text, header->uncompressed_length);
if (ziperr != ZIPERR_NONE)
{
err = MCERR_ZIP_ERROR;
goto done;
}
layout_text[header->uncompressed_length] = '\0';
/* parse the layout text */
state.layout_xml = xml_string_read(layout_text, NULL);
if (state.layout_xml == NULL)
{
err = MCERR_XML_ERROR;
goto done;
}
/* locate the PCB node */
if (!find_pcb_and_resource_nodes(state.layout_xml, &state.pcb_node, &state.resources_node))
{
err = MCERR_NO_PCB_OR_RESOURCES;
goto done;
}
/* get the PCB resource_type */
pcb_type = xml_get_attribute_string(state.pcb_node, "type", "");
state.multicart->pcb_type = pool_strdup_lib(state.multicart->data->pool, pcb_type);
if (state.multicart->pcb_type == NULL)
{
err = MCERR_OUT_OF_MEMORY;
goto done;
}
state.multicart->gamedrv_name = pool_strdup_lib(state.multicart->data->pool, gamedrv);
if (state.multicart->gamedrv_name == NULL)
{
err = MCERR_OUT_OF_MEMORY;
goto done;
}
/* do we have to load resources? */
if (load_flags & MULTICART_FLAGS_LOAD_RESOURCES)
{
err = load_all_resources(&state);
if (err != MCERR_NONE)
goto done;
err = load_all_sockets(&state);
if (err != MCERR_NONE)
goto done;
}
err = MCERR_NONE;
done:
if (pool != NULL)
pool_free_lib(pool);
if (state.zip != NULL)
zip_file_close(state.zip);
if (layout_text != NULL)
free(layout_text);
if (state.layout_xml != NULL)
xml_file_free(state.layout_xml);
if ((err != MCERR_NONE) && (state.multicart != NULL))
{
multicart_close(state.multicart);
state.multicart = NULL;
}
*cart = state.multicart;
return err;
}
/*-------------------------------------------------
multicart_close - closes a multicart
-------------------------------------------------*/
void multicart_close(multicart_t *cart)
{
save_ram_resources(cart);
pool_free_lib(cart->data->pool);
}

100
src/emu/imagedev/multcart.h Normal file
View File

@ -0,0 +1,100 @@
/*********************************************************************
multcart.h
Multi-cartridge handling code
*********************************************************************/
#ifndef __MULTCART_H__
#define __MULTCART_H__
#include "osdcore.h"
/***************************************************************************
TYPE DEFINITIONS
***************************************************************************/
enum _multicart_load_flags
{
MULTICART_FLAGS_DONT_LOAD_RESOURCES = 0x00,
MULTICART_FLAGS_LOAD_RESOURCES = 0x01
};
typedef enum _multicart_load_flags multicart_load_flags;
enum _multicart_resource_type
{
MULTICART_RESOURCE_TYPE_INVALID,
MULTICART_RESOURCE_TYPE_ROM,
MULTICART_RESOURCE_TYPE_RAM
};
typedef enum _multicart_resource_type multicart_resource_type;
typedef struct _multicart_resource multicart_resource;
struct _multicart_resource
{
const char * id;
const char * filename;
multicart_resource * next;
multicart_resource_type type;
UINT32 length;
void * ptr;
};
typedef struct _multicart_socket multicart_socket;
struct _multicart_socket
{
const char * id;
multicart_socket * next;
const multicart_resource * resource;
void * ptr;
};
typedef struct _multicart_private multicart_private;
typedef struct _multicart_t multicart_t;
struct _multicart_t
{
const multicart_resource * resources;
const multicart_socket * sockets;
const char * pcb_type;
const char * gamedrv_name; /* need this to find the path to the nvram files */
multicart_private * data;
};
enum _multicart_open_error
{
MCERR_NONE,
MCERR_NOT_MULTICART,
MCERR_CORRUPT,
MCERR_OUT_OF_MEMORY,
MCERR_XML_ERROR,
MCERR_INVALID_FILE_REF,
MCERR_ZIP_ERROR,
MCERR_MISSING_RAM_LENGTH,
MCERR_INVALID_RAM_SPEC,
MCERR_UNKNOWN_RESOURCE_TYPE,
MCERR_INVALID_RESOURCE_REF,
MCERR_INVALID_FILE_FORMAT,
MCERR_MISSING_LAYOUT,
MCERR_NO_PCB_OR_RESOURCES
};
typedef enum _multicart_open_error multicart_open_error;
const char *multicart_error_text(multicart_open_error error);
/***************************************************************************
PROTOTYPES
***************************************************************************/
/* opens a multicart */
multicart_open_error multicart_open(const char *filename, const char *drvname, multicart_load_flags load_flags, multicart_t **cart);
/* closes a multicart */
void multicart_close(multicart_t *cart);
#endif /* __MULTCART_H__ */

116
src/emu/imagedev/printer.c Normal file
View File

@ -0,0 +1,116 @@
/****************************************************************************
printer.c
Code for handling printer devices
****************************************************************************/
#include "emu.h"
#include "printer.h"
/***************************************************************************
IMPLEMENTATION
***************************************************************************/
/*-------------------------------------------------
printer_is_ready - checks to see if a printer
is ready
-------------------------------------------------*/
int printer_is_ready(device_t *printer)
{
device_image_interface *image = dynamic_cast<device_image_interface *>(printer);
/* if there is a file attached to it, it's online */
return image->exists() != 0;
}
/*-------------------------------------------------
printer_output - outputs data to a printer
-------------------------------------------------*/
void printer_output(device_t *printer, UINT8 data)
{
device_image_interface *image = dynamic_cast<device_image_interface *>(printer);
if (image->exists())
{
image->fwrite(&data, 1);
}
}
/*-------------------------------------------------
DEVICE_IMAGE_LOAD( printer )
-------------------------------------------------*/
static DEVICE_IMAGE_LOAD( printer )
{
const printer_config *conf = (const printer_config *)downcast<const legacy_image_device_config_base &>(image.device().baseconfig()).inline_config();
/* send notify that the printer is now online */
if (conf != NULL && conf->online != NULL)
conf->online(image, TRUE);
/* we don't need to do anything special */
return IMAGE_INIT_PASS;
}
/*-------------------------------------------------
DEVICE_IMAGE_UNLOAD( printer )
-------------------------------------------------*/
static DEVICE_IMAGE_UNLOAD( printer )
{
const printer_config *conf = (const printer_config *)downcast<const legacy_image_device_config_base &>(image.device().baseconfig()).inline_config();
/* send notify that the printer is now offline */
if (conf != NULL && conf->online != NULL)
conf->online(image, FALSE);
}
/*-------------------------------------------------
DEVICE_START(printer)
-------------------------------------------------*/
static DEVICE_START(printer)
{
}
/*-------------------------------------------------
DEVICE_GET_INFO(printer)
-------------------------------------------------*/
DEVICE_GET_INFO(printer)
{
switch(state)
{
/* --- the following bits of info are returned as 64-bit signed integers --- */
case DEVINFO_INT_TOKEN_BYTES: info->i = 1; break;
case DEVINFO_INT_INLINE_CONFIG_BYTES: info->i = sizeof(printer_config); break;
case DEVINFO_INT_IMAGE_TYPE: info->i = IO_PRINTER; break;
case DEVINFO_INT_IMAGE_READABLE: info->i = 0; break;
case DEVINFO_INT_IMAGE_WRITEABLE: info->i = 1; break;
case DEVINFO_INT_IMAGE_CREATABLE: info->i = 1; break;
/* --- the following bits of info are returned as pointers to data or functions --- */
case DEVINFO_FCT_START: info->start = DEVICE_START_NAME(printer); break;
case DEVINFO_FCT_IMAGE_LOAD: info->f = (genf *) DEVICE_IMAGE_LOAD_NAME(printer); break;
case DEVINFO_FCT_IMAGE_UNLOAD: info->f = (genf *) DEVICE_IMAGE_UNLOAD_NAME(printer); break;
/* --- the following bits of info are returned as NULL-terminated strings --- */
case DEVINFO_STR_NAME: strcpy(info->s, "Printer"); break;
case DEVINFO_STR_FAMILY: strcpy(info->s, "Printer"); break;
case DEVINFO_STR_SOURCE_FILE: strcpy(info->s, __FILE__); break;
case DEVINFO_STR_IMAGE_FILE_EXTENSIONS: strcpy(info->s, "prn"); break;
}
}
DEFINE_LEGACY_IMAGE_DEVICE(PRINTER, printer);

View File

@ -0,0 +1,48 @@
/****************************************************************************
printer.h
Code for handling printer devices
****************************************************************************/
#ifndef __PRINTER_H__
#define __PRINTER_H__
#include "image.h"
/***************************************************************************
TYPE DEFINITIONS
***************************************************************************/
typedef void (*online_func)(device_t *device, int state);
typedef struct _printer_config printer_config;
struct _printer_config
{
online_func online;
};
DECLARE_LEGACY_IMAGE_DEVICE(PRINTER, printer);
#define MCFG_PRINTER_ADD(_tag) \
MCFG_DEVICE_ADD(_tag, PRINTER, 0) \
#define MCFG_PRINTER_ONLINE(_online) \
MCFG_DEVICE_CONFIG_DATAPTR(printer_config, online, _online)
/***************************************************************************
FUNCTION PROTOTYPES
***************************************************************************/
/* checks to see if a printer is ready */
int printer_is_ready(device_t *printer);
/* outputs data to a printer */
void printer_output(device_t *printer, UINT8 data);
#endif /* __PRINTER_H__ */

373
src/emu/imagedev/snapquik.c Normal file
View File

@ -0,0 +1,373 @@
/*********************************************************************
snapquik.h
Snapshots and quickloads
*********************************************************************/
#include "emu.h"
#include "snapquik.h"
/***************************************************************************
TYPE DEFINITIONS
***************************************************************************/
typedef struct _snapquick_token snapquick_token;
struct _snapquick_token
{
emu_timer *timer;
snapquick_load_func load;
};
/***************************************************************************
INLINE FUNCTIONS
***************************************************************************/
/*-------------------------------------------------
assert_is_snapshot_or_quickload - asserts/confirms
that a given device is a snapshot or quickload
-------------------------------------------------*/
INLINE void assert_is_snapshot_or_quickload(device_t *device)
{
assert(device != NULL);
assert(downcast<const legacy_device_config_base &>(device->baseconfig()).inline_config() != NULL);
assert((device->type() == SNAPSHOT) || (device->type() == QUICKLOAD)
|| (device->type() == Z80BIN));
}
/*-------------------------------------------------
get_token - safely gets the snapshot/quickload data
-------------------------------------------------*/
INLINE snapquick_token *get_token(device_t *device)
{
assert_is_snapshot_or_quickload(device);
return (snapquick_token *) downcast<legacy_device_base *>(device)->token();
}
/*-------------------------------------------------
get_config - safely gets the quickload config
-------------------------------------------------*/
INLINE const snapquick_config *get_config(device_t *device)
{
assert_is_snapshot_or_quickload(device);
return (const snapquick_config *) downcast<const legacy_device_config_base &>(device->baseconfig()).inline_config();
}
INLINE const snapquick_config *get_config_dev(const device_config *device)
{
assert(device != NULL);
assert((device->type() == SNAPSHOT) || (device->type() == QUICKLOAD)
|| (device->type() == Z80BIN));
return (const snapquick_config *) downcast<const legacy_device_config_base *>(device)->inline_config();
}
/*-------------------------------------------------
log_quickload - logs and displays useful
data for the end user
-------------------------------------------------*/
void log_quickload(const char *type, UINT32 start, UINT32 length, UINT32 exec, const char *exec_format)
{
astring tempstring;
logerror("Loading %04X bytes of RAM at %04X\n", length, start);
tempstring.catprintf("Quickload type: %s Length: %d bytes\n", type, length);
tempstring.catprintf("Start: 0x%04X End: 0x%04X Exec: ", start, start + length - 1);
logerror("Quickload loaded.\n");
if (!mame_stricmp(exec_format, EXEC_NA))
tempstring.cat("N/A");
else
{
logerror("Execution can resume with ");
logerror(exec_format, exec);
logerror("\n");
tempstring.catprintf(exec_format, exec);
}
ui_popup_time(10, "%s", tempstring.cstr());
}
/***************************************************************************
IMPLEMENTATION
***************************************************************************/
/*-------------------------------------------------
TIMER_CALLBACK(process_snapshot_or_quickload)
-------------------------------------------------*/
static TIMER_CALLBACK(process_snapshot_or_quickload)
{
device_image_interface *image = (device_image_interface *) ptr;
snapquick_token *token = get_token(&image->device());
/* invoke the load */
(*token->load)(*image,
image->filetype(),
image->length());
/* unload the device */
image->unload();
}
/*-------------------------------------------------
DEVICE_START( snapquick )
-------------------------------------------------*/
static DEVICE_START( snapquick )
{
snapquick_token *token = get_token(device);
/* allocate a timer */
token->timer = timer_alloc(device->machine, process_snapshot_or_quickload, (void *) dynamic_cast<device_image_interface *>(device));
}
/*-------------------------------------------------
DEVICE_IMAGE_LOAD( snapquick )
-------------------------------------------------*/
static DEVICE_IMAGE_LOAD( snapquick )
{
const snapquick_config *config = get_config(image);
snapquick_token *token = get_token(image);
/* locate the load function */
token->load = (snapquick_load_func) reinterpret_cast<snapquick_load_func>(image.get_device_specific_call());
/* adjust the timer */
timer_adjust_oneshot(
token->timer,
attotime_make(config->delay_seconds, config->delay_attoseconds),
0);
return IMAGE_INIT_PASS;
}
/*-------------------------------------------------
DEVICE_GET_INFO(snapquick) - device getinfo
function
-------------------------------------------------*/
static DEVICE_GET_INFO(snapquick)
{
switch(state)
{
/* --- the following bits of info are returned as 64-bit signed integers --- */
case DEVINFO_INT_TOKEN_BYTES: info->i = sizeof(snapquick_token); break;
case DEVINFO_INT_INLINE_CONFIG_BYTES: info->i = sizeof(snapquick_config); break;
case DEVINFO_INT_IMAGE_READABLE: info->i = 1; break;
case DEVINFO_INT_IMAGE_WRITEABLE: info->i = 0; break;
case DEVINFO_INT_IMAGE_CREATABLE: info->i = 0; break;
/* --- the following bits of info are returned as pointers to functions --- */
case DEVINFO_FCT_START: info->start = DEVICE_START_NAME(snapquick); break;
case DEVINFO_FCT_IMAGE_LOAD: info->f = (genf *) DEVICE_IMAGE_LOAD_NAME(snapquick); break;
case DEVINFO_FCT_SNAPSHOT_QUICKLOAD_LOAD: info->f = (genf *) get_config_dev(device)->load; break;
/* --- the following bits of info are returned as NULL-terminated strings --- */
case DEVINFO_STR_SOURCE_FILE: strcpy(info->s, __FILE__); break;
case DEVINFO_STR_IMAGE_FILE_EXTENSIONS: strcpy(info->s, get_config_dev(device)->file_extensions); break;
}
}
/*-------------------------------------------------
DEVICE_GET_INFO(snapshot) - device getinfo
function
-------------------------------------------------*/
DEVICE_GET_INFO(snapshot)
{
switch(state)
{
/* --- the following bits of info are returned as 64-bit signed integers --- */
case DEVINFO_INT_IMAGE_TYPE: info->i = IO_SNAPSHOT; break;
/* --- the following bits of info are returned as NULL-terminated strings --- */
case DEVINFO_STR_NAME: strcpy(info->s, "Snapshot"); break;
case DEVINFO_STR_FAMILY: strcpy(info->s, "Snapshot"); break;
default: DEVICE_GET_INFO_CALL(snapquick); break;
}
}
/*-------------------------------------------------
DEVICE_GET_INFO(quickload) - device getinfo
function
-------------------------------------------------*/
DEVICE_GET_INFO(quickload)
{
switch(state)
{
/* --- the following bits of info are returned as 64-bit signed integers --- */
case DEVINFO_INT_IMAGE_TYPE: info->i = IO_QUICKLOAD; break;
/* --- the following bits of info are returned as NULL-terminated strings --- */
case DEVINFO_STR_NAME: strcpy(info->s, "Quickload"); break;
case DEVINFO_STR_FAMILY: strcpy(info->s, "Quickload"); break;
default: DEVICE_GET_INFO_CALL(snapquick); break;
}
}
/*-------------------------------------------------
z80bin_load_file - load a z80bin file into
memory
-------------------------------------------------*/
static int z80bin_load_file(device_image_interface *image, const char *file_type, UINT16 *exec_addr, UINT16 *start_addr, UINT16 *end_addr )
{
int ch;
UINT16 args[3];
UINT16 i=0, j, size;
UINT8 data;
char pgmname[256];
char message[256];
image->fseek(7, SEEK_SET);
while((ch = image->fgetc()) != 0x1A)
{
if (ch == EOF)
{
image->seterror(IMAGE_ERROR_INVALIDIMAGE, "Unexpected EOF while getting file name");
image->message(" Unexpected EOF while getting file name");
return IMAGE_INIT_FAIL;
}
if (ch != '\0')
{
if (i >= (ARRAY_LENGTH(pgmname) - 1))
{
image->seterror(IMAGE_ERROR_INVALIDIMAGE, "File name too long");
image->message(" File name too long");
return IMAGE_INIT_FAIL;
}
pgmname[i] = ch; /* build program name */
i++;
}
}
pgmname[i] = '\0'; /* terminate string with a null */
if (image->fread(args, sizeof(args)) != sizeof(args))
{
image->seterror(IMAGE_ERROR_INVALIDIMAGE, "Unexpected EOF while getting file size");
image->message(" Unexpected EOF while getting file size");
return IMAGE_INIT_FAIL;
}
exec_addr[0] = LITTLE_ENDIANIZE_INT16(args[0]);
start_addr[0] = LITTLE_ENDIANIZE_INT16(args[1]);
end_addr[0] = LITTLE_ENDIANIZE_INT16(args[2]);
size = (end_addr[0] - start_addr[0] + 1) & 0xffff;
/* display a message about the loaded quickload */
image->message(" %s\nsize=%04X : start=%04X : end=%04X : exec=%04X",pgmname,size,start_addr[0],end_addr[0],exec_addr[0]);
for (i = 0; i < size; i++)
{
j = (start_addr[0] + i) & 0xffff;
if (image->fread(&data, 1) != 1)
{
snprintf(message, ARRAY_LENGTH(message), "%s: Unexpected EOF while writing byte to %04X", pgmname, (unsigned) j);
image->seterror(IMAGE_ERROR_INVALIDIMAGE, message);
image->message("%s: Unexpected EOF while writing byte to %04X", pgmname, (unsigned) j);
return IMAGE_INIT_FAIL;
}
cputag_get_address_space(image->device().machine,"maincpu",ADDRESS_SPACE_PROGRAM)->write_byte(j, data);
}
return IMAGE_INIT_PASS;
}
/*-------------------------------------------------
QUICKLOAD_LOAD( z80bin )
-------------------------------------------------*/
static QUICKLOAD_LOAD( z80bin )
{
const z80bin_config *config;
UINT16 exec_addr, start_addr, end_addr;
int autorun;
/* load the binary into memory */
if (z80bin_load_file(&image, file_type, &exec_addr, &start_addr, &end_addr) == IMAGE_INIT_FAIL)
return IMAGE_INIT_FAIL;
/* is this file executable? */
if (exec_addr != 0xffff)
{
config = (const z80bin_config *)downcast<const legacy_device_config_base &>(image.device().baseconfig()).inline_config();
/* check to see if autorun is on (I hate how this works) */
autorun = input_port_read_safe(image.device().machine, "CONFIG", 0xFF) & 1;
/* start program */
if (config->execute != NULL)
{
(*config->execute)(image.device().machine, start_addr, end_addr, exec_addr, autorun);
}
else
{
if (autorun)
cpu_set_reg(image.device().machine->device("maincpu"), STATE_GENPC, exec_addr);
}
}
return IMAGE_INIT_PASS;
}
/*-------------------------------------------------
DEVICE_GET_INFO(z80bin)
-------------------------------------------------*/
DEVICE_GET_INFO(z80bin)
{
/* quickload */
switch(state)
{
/* --- the following bits of info are returned as 64-bit signed integers --- */
case DEVINFO_INT_INLINE_CONFIG_BYTES: info->i = sizeof(z80bin_config); break;
/* --- the following bits of info are returned as NULL-terminated strings --- */
case DEVINFO_STR_SOURCE_FILE: strcpy(info->s, __FILE__); break;
case DEVINFO_STR_IMAGE_FILE_EXTENSIONS: strcpy(info->s, "bin"); break;
/* --- the following bits of info are returned as pointers to functions --- */
case DEVINFO_FCT_SNAPSHOT_QUICKLOAD_LOAD: info->f = (genf *) quickload_load_z80bin; break;
default: DEVICE_GET_INFO_CALL(quickload); break;
}
}
DEFINE_LEGACY_IMAGE_DEVICE(Z80BIN, z80bin);
DEFINE_LEGACY_IMAGE_DEVICE(SNAPSHOT, snapshot);
DEFINE_LEGACY_IMAGE_DEVICE(QUICKLOAD, quickload);

115
src/emu/imagedev/snapquik.h Normal file
View File

@ -0,0 +1,115 @@
/*********************************************************************
snapquik.h
Snapshots and quickloads
*********************************************************************/
#ifndef __SNAPQUIK_H__
#define __SNAPQUIK_H__
#include "image.h"
#include "ui.h"
/***************************************************************************
CONSTANTS
***************************************************************************/
enum
{
DEVINFO_FCT_SNAPSHOT_QUICKLOAD_LOAD = DEVINFO_FCT_DEVICE_SPECIFIC
};
/***************************************************************************
MACROS
***************************************************************************/
DECLARE_LEGACY_IMAGE_DEVICE(SNAPSHOT, snapshot);
DECLARE_LEGACY_IMAGE_DEVICE(QUICKLOAD, quickload);
DECLARE_LEGACY_IMAGE_DEVICE(Z80BIN, z80bin);
#define SNAPSHOT_LOAD_NAME(name) snapshot_load_##name
#define SNAPSHOT_LOAD(name) int SNAPSHOT_LOAD_NAME(name)(device_image_interface &image, const char *file_type, int snapshot_size)
#define QUICKLOAD_LOAD_NAME(name) quickload_load_##name
#define QUICKLOAD_LOAD(name) int QUICKLOAD_LOAD_NAME(name)(device_image_interface &image, const char *file_type, int quickload_size)
#define Z80BIN_EXECUTE_NAME(name) z80bin_execute_##name
#define Z80BIN_EXECUTE(name) void Z80BIN_EXECUTE_NAME(name)(running_machine *machine, UINT16 start_address, UINT16 end_address, UINT16 execute_address, int autorun)
#define LOAD_REG(_cpu, _reg, _data) \
do { \
cpu_set_reg(_cpu, _reg, (_data)); \
} while (0)
#define EXEC_NA "N/A"
#define z80bin_execute_default NULL
/***************************************************************************
TYPE DEFINITIONS
***************************************************************************/
typedef int (*snapquick_load_func)(device_image_interface &image, const char *file_type, int file_size);
typedef struct _snapquick_config snapquick_config;
struct _snapquick_config
{
snapquick_load_func load; /* loading function */
const char * file_extensions; /* file extensions */
seconds_t delay_seconds; /* loading delay (seconds) */
attoseconds_t delay_attoseconds; /* loading delay (attoseconds) */
};
typedef void (*z80bin_execute_func)(running_machine *machine, UINT16 start_address, UINT16 end_address, UINT16 execute_address, int autorun);
typedef struct _z80bin_config z80bin_config;
struct _z80bin_config
{
snapquick_config base;
z80bin_execute_func execute;
};
/***************************************************************************
SNAPSHOT DEVICE CONFIGURATION MACROS
***************************************************************************/
#define MCFG_SNAPSHOT_ADD(_tag, _load, _file_extensions, _delay) \
MCFG_DEVICE_ADD(_tag, SNAPSHOT, 0) \
MCFG_DEVICE_CONFIG_DATAPTR(snapquick_config, load, SNAPSHOT_LOAD_NAME(_load)) \
MCFG_DEVICE_CONFIG_DATAPTR(snapquick_config, file_extensions, _file_extensions) \
MCFG_DEVICE_CONFIG_DATA64(snapquick_config, delay_seconds, (seconds_t) (_delay)) \
MCFG_DEVICE_CONFIG_DATA64(snapquick_config, delay_attoseconds, (attoseconds_t) (((_delay) - (int)(_delay)) * ATTOSECONDS_PER_SECOND)) \
/***************************************************************************
QUICKLOAD DEVICE CONFIGURATION MACROS
***************************************************************************/
#define MCFG_QUICKLOAD_ADD(_tag, _load, _file_extensions, _delay) \
MCFG_DEVICE_ADD(_tag, QUICKLOAD, 0) \
MCFG_DEVICE_CONFIG_DATAPTR(snapquick_config, load, QUICKLOAD_LOAD_NAME(_load)) \
MCFG_DEVICE_CONFIG_DATAPTR(snapquick_config, file_extensions, _file_extensions) \
MCFG_DEVICE_CONFIG_DATA64(snapquick_config, delay_seconds, (seconds_t) (_delay)) \
MCFG_DEVICE_CONFIG_DATA64(snapquick_config, delay_attoseconds, (attoseconds_t) (((_delay) - (int)(_delay)) * ATTOSECONDS_PER_SECOND)) \
/***************************************************************************
Z80BIN QUICKLOAD DEVICE CONFIGURATION MACROS
***************************************************************************/
#define MCFG_Z80BIN_QUICKLOAD_ADD(_tag, _execute, _delay) \
MCFG_DEVICE_ADD(_tag, Z80BIN, 0) \
MCFG_DEVICE_CONFIG_DATA64(snapquick_config, delay_seconds, (seconds_t) (_delay)) \
MCFG_DEVICE_CONFIG_DATA64(snapquick_config, delay_attoseconds, (attoseconds_t) (((_delay) - (int)(_delay)) * ATTOSECONDS_PER_SECOND)) \
MCFG_DEVICE_CONFIG_DATAPTR(z80bin_config, execute, Z80BIN_EXECUTE_NAME(_execute))
/***************************************************************************
FUNCTION PROTOTYPES
***************************************************************************/
void log_quickload(const char *type, UINT32 start, UINT32 length, UINT32 exec, const char *exec_format);
#endif /* __SNAPQUIK_H__ */

291
src/emu/imagedev/wavfile.c Normal file
View File

@ -0,0 +1,291 @@
/*********************************************************************
wavfile.c
Format code for wave (*.wav) files
*********************************************************************/
#include <stdio.h>
#include <assert.h>
#include "wavfile.h"
#include "cassimg.h"
static const char magic1[4] = { 'R', 'I', 'F', 'F' };
static const char magic2[4] = { 'W', 'A', 'V', 'E' };
static const char format_tag_id[4] = { 'f', 'm', 't', ' ' };
static const char data_tag_id[4] = { 'd', 'a', 't', 'a' };
#define WAV_FORMAT_PCM 1
static UINT32 get_leuint32(const void *ptr)
{
UINT32 value;
memcpy(&value, ptr, sizeof(value));
return LITTLE_ENDIANIZE_INT32(value);
}
static UINT16 get_leuint16(const void *ptr)
{
UINT16 value;
memcpy(&value, ptr, sizeof(value));
return LITTLE_ENDIANIZE_INT16(value);
}
static void put_leuint32(void *ptr, UINT32 value)
{
value = LITTLE_ENDIANIZE_INT32(value);
memcpy(ptr, &value, sizeof(value));
}
static void put_leuint16(void *ptr, UINT16 value)
{
value = LITTLE_ENDIANIZE_INT16(value);
memcpy(ptr, &value, sizeof(value));
}
static casserr_t wavfile_process(cassette_image *cassette, struct CassetteOptions *opts,
int read_waveform)
{
UINT8 file_header[12];
UINT8 tag_header[8];
UINT8 format_tag[16];
UINT32 stated_size;
UINT64 file_size;
UINT32 tag_size;
UINT32 tag_samples;
UINT64 offset;
int format_specified = FALSE;
UINT16 format_type = 0;
UINT32 bytes_per_second = 0;
UINT16 block_align = 0;
int waveform_flags = 0;
/* read header */
cassette_image_read(cassette, file_header, 0, sizeof(file_header));
offset = sizeof(file_header);
/* check magic numbers */
if (memcmp(&file_header[0], magic1, 4))
return CASSETTE_ERROR_INVALIDIMAGE;
if (memcmp(&file_header[8], magic2, 4))
return CASSETTE_ERROR_INVALIDIMAGE;
/* read and sanity check size */
stated_size = get_leuint32(&file_header[4]) + 8;
file_size = cassette_image_size(cassette);
if (stated_size > file_size)
stated_size = (UINT32) file_size;
while(offset < stated_size)
{
cassette_image_read(cassette, tag_header, offset, sizeof(tag_header));
tag_size = get_leuint32(&tag_header[4]);
offset += sizeof(tag_header);
if (!memcmp(tag_header, format_tag_id, 4))
{
/* format tag */
if (format_specified || (tag_size < sizeof(format_tag)))
return CASSETTE_ERROR_INVALIDIMAGE;
format_specified = TRUE;
cassette_image_read(cassette, format_tag, offset, sizeof(format_tag));
format_type = get_leuint16(&format_tag[0]);
opts->channels = get_leuint16(&format_tag[2]);
opts->sample_frequency = get_leuint32(&format_tag[4]);
bytes_per_second = get_leuint32(&format_tag[8]);
block_align = get_leuint16(&format_tag[12]);
opts->bits_per_sample = get_leuint16(&format_tag[14]);
if (format_type != WAV_FORMAT_PCM)
return CASSETTE_ERROR_INVALIDIMAGE;
if (opts->sample_frequency * opts->bits_per_sample * opts->channels / 8 != bytes_per_second)
return CASSETTE_ERROR_INVALIDIMAGE;
switch(opts->bits_per_sample)
{
case 8:
waveform_flags = CASSETTE_WAVEFORM_8BIT;
break;
case 16:
waveform_flags = CASSETTE_WAVEFORM_16BITLE;
break;
case 32:
waveform_flags = CASSETTE_WAVEFORM_32BITLE;
break;
default:
return CASSETTE_ERROR_INVALIDIMAGE;
}
}
else if (!memcmp(tag_header, data_tag_id, 4))
{
/* data tag */
if (!format_specified)
return CASSETTE_ERROR_INVALIDIMAGE;
if (read_waveform)
{
tag_samples = tag_size / (opts->bits_per_sample / 8) / opts->channels;
cassette_read_samples(cassette, opts->channels, 0.0, tag_samples / ((double) opts->sample_frequency),
tag_samples, offset, waveform_flags);
}
}
else
{
/* ignore other tags */
}
offset += tag_size;
}
return CASSETTE_ERROR_SUCCESS;
}
static casserr_t wavfile_identify(cassette_image *cassette, struct CassetteOptions *opts)
{
return wavfile_process(cassette, opts, FALSE);
}
static casserr_t wavfile_load(cassette_image *cassette)
{
struct CassetteOptions opts;
memset(&opts, 0, sizeof(opts));
return wavfile_process(cassette, &opts, TRUE);
}
static casserr_t wavfile_save(cassette_image *cassette, const struct CassetteInfo *info)
{
casserr_t err;
UINT8 consolidated_header[12 + 8 + 16 + 8];
UINT8 *header = &consolidated_header[0];
UINT8 *format_tag_header = &consolidated_header[12];
UINT8 *format_tag_data = &consolidated_header[12 + 8];
UINT8 *data_tag_header = &consolidated_header[12 + 8 + 16];
UINT32 file_size;
UINT32 bytes_per_second;
UINT16 bits_per_sample;
UINT32 data_size;
size_t bytes_per_sample = 2;
int waveform_flags = CASSETTE_WAVEFORM_16BITLE;
UINT16 block_align;
bits_per_sample = (UINT16) (bytes_per_sample * 8);
bytes_per_second = info->sample_frequency * bytes_per_sample * info->channels;
data_size = (UINT32) (info->sample_count * bytes_per_sample * info->channels);
file_size = data_size + sizeof(consolidated_header) - 8;
block_align = (UINT16) (bytes_per_sample * info->channels);
/* set up header */
memcpy(&header[0], magic1, 4);
memcpy(&header[8], magic2, 4);
put_leuint32(&header[4], file_size);
/* set up format tag */
memcpy(&format_tag_header[0], format_tag_id, 4);
put_leuint32(&format_tag_header[4], 16);
put_leuint16(&format_tag_data[0], WAV_FORMAT_PCM);
put_leuint16(&format_tag_data[2], info->channels);
put_leuint32(&format_tag_data[4], info->sample_frequency);
put_leuint32(&format_tag_data[8], bytes_per_second);
put_leuint16(&format_tag_data[12], block_align);
put_leuint16(&format_tag_data[14], bits_per_sample);
/* set up data tag */
memcpy(&data_tag_header[0], data_tag_id, 4);
put_leuint32(&data_tag_header[4], data_size);
/* write consolidated header */
cassette_image_write(cassette, consolidated_header, 0, sizeof(consolidated_header));
/* write out the actual data */
err = cassette_write_samples(cassette, info->channels, 0.0, info->sample_count
/ (double) info->sample_frequency, info->sample_count, sizeof(consolidated_header),
waveform_flags);
if (err)
return err;
return CASSETTE_ERROR_SUCCESS;
}
const struct CassetteFormat wavfile_format =
{
"wav",
wavfile_identify,
wavfile_load,
wavfile_save
};
/*********************************************************************
wavfile_testload()
This is a hokey function used to test the cassette wave loading
system, specifically to test that when one loads a WAV file image
that the resulting info queried will be the same data in the WAV.
This code has already identified some rounding errors
*********************************************************************/
#ifdef UNUSED_FUNCTION
void wavfile_testload(const char *fname)
{
cassette_image *cassette;
FILE *f;
long offset;
int freq, samples, i;
INT32 cassamp;
INT16 wavsamp;
f = fopen(fname, "rb");
if (!f)
return;
if (cassette_open(f, &stdio_ioprocs, &wavfile_format, CASSETTE_FLAG_READONLY, &cassette))
{
fclose(f);
return;
}
offset = 44;
freq = 44100;
samples = 5667062;
for (i = 0; i < samples; i++)
{
cassette_get_sample(cassette, 0, i / (double) freq, 0.0, &cassamp);
fseek(f, offset + i * 2, SEEK_SET);
fread(&wavsamp, 1, 2, f);
assert(cassamp == (((UINT32) wavsamp) << 16));
}
cassette_close(cassette);
fclose(f);
}
#endif

View File

@ -0,0 +1,16 @@
/*********************************************************************
wavfile.h
Format code for wave (*.wav) files
*********************************************************************/
#ifndef WAVFILE_H
#define WAVFILE_H
#include "cassimg.h"
extern const struct CassetteFormat wavfile_format;
#endif /* WAVFILE_H */

View File

@ -7,10 +7,7 @@
#include "emu.h" #include "emu.h"
#include "idectrl.h" #include "idectrl.h"
#include "debugger.h" #include "debugger.h"
#include "imagedev/harddriv.h"
#ifdef MESS
#include "devices/harddriv.h"
#endif
/*************************************************************************** /***************************************************************************
DEBUGGING DEBUGGING

View File

@ -8,9 +8,7 @@
#include "scsidev.h" #include "scsidev.h"
#include "cdrom.h" #include "cdrom.h"
#include "sound/cdda.h" #include "sound/cdda.h"
#ifdef MESS #include "imagedev/chd_cd.h"
#include "devices/chd_cd.h"
#endif
#include "scsicd.h" #include "scsicd.h"
typedef struct typedef struct

View File

@ -7,10 +7,7 @@
#include "emu.h" #include "emu.h"
#include "scsidev.h" #include "scsidev.h"
#include "harddisk.h" #include "harddisk.h"
#include "imagedev/harddriv.h"
#ifdef MESS
#include "devices/harddriv.h"
#endif
#include "scsihd.h" #include "scsihd.h"
typedef struct typedef struct

View File

@ -15,16 +15,13 @@
#include "emu.h" #include "emu.h"
#include "streams.h" #include "streams.h"
#ifdef MESS #include "imagedev/cassette.h"
#include "devices/cassette.h"
#endif
#include "wave.h" #include "wave.h"
#define ALWAYS_PLAY_SOUND 0 #define ALWAYS_PLAY_SOUND 0
static STREAM_UPDATE( wave_sound_update ) static STREAM_UPDATE( wave_sound_update )
{ {
#ifdef MESS
device_image_interface *image = (device_image_interface *)param; device_image_interface *image = (device_image_interface *)param;
int speakers = speaker_output_count(image->device().machine->config); int speakers = speaker_output_count(image->device().machine->config);
cassette_image *cassette; cassette_image *cassette;
@ -62,7 +59,6 @@ static STREAM_UPDATE( wave_sound_update )
if (speakers > 1) if (speakers > 1)
memset(right_buffer, 0, sizeof(*right_buffer) * samples); memset(right_buffer, 0, sizeof(*right_buffer) * samples);
} }
#endif
} }
@ -74,9 +70,7 @@ static DEVICE_START( wave )
assert( device != NULL ); assert( device != NULL );
assert( device->baseconfig().static_config() != NULL ); assert( device->baseconfig().static_config() != NULL );
int speakers = speaker_output_count(device->machine->config); int speakers = speaker_output_count(device->machine->config);
#ifdef MESS
image = dynamic_cast<device_image_interface *>(device->machine->device( (const char *)device->baseconfig().static_config())); image = dynamic_cast<device_image_interface *>(device->machine->device( (const char *)device->baseconfig().static_config()));
#endif
if (speakers > 1) if (speakers > 1)
stream_create(device, 0, 2, device->machine->sample_rate, (void *)image, wave_sound_update); stream_create(device, 0, 2, device->machine->sample_rate, (void *)image, wave_sound_update);
else else

View File

@ -23,6 +23,8 @@
#include "uimenu.h" #include "uimenu.h"
#include "zippath.h" #include "zippath.h"
#include "unicode.h" #include "unicode.h"
#include "imagedev/cassette.h"
#include "imagedev/bitbngr.h"
@ -1014,3 +1016,426 @@ void ui_image_menu_image_info(running_machine *machine, ui_menu *menu, void *par
/* process the menu */ /* process the menu */
ui_menu_process(machine, menu, 0); ui_menu_process(machine, menu, 0);
} }
/***************************************************************************
TYPE DEFINITIONS
***************************************************************************/
#define TAPECMD_NULL ((void *) 0x0000)
#define TAPECMD_STOP ((void *) 0x0001)
#define TAPECMD_PLAY ((void *) 0x0002)
#define TAPECMD_RECORD ((void *) 0x0003)
#define TAPECMD_REWIND ((void *) 0x0004)
#define TAPECMD_FAST_FORWARD ((void *) 0x0005)
#define TAPECMD_SLIDER ((void *) 0x0006)
#define TAPECMD_SELECT ((void *) 0x0007)
#define BITBANGERCMD_SELECT ((void *) 0x0000)
#define BITBANGERCMD_MODE ((void *) 0x0001)
#define BITBANGERCMD_BAUD ((void *) 0x0002)
#define BITBANGERCMD_TUNE ((void *) 0x0003)
typedef struct _tape_control_menu_state tape_control_menu_state;
struct _tape_control_menu_state
{
int index;
device_image_interface *device;
};
typedef struct _bitbanger_control_menu_state bitbanger_control_menu_state;
struct _bitbanger_control_menu_state
{
int index;
device_image_interface *device;
};
/***************************************************************************
IMPLEMENTATION
***************************************************************************/
/*-------------------------------------------------
cassette_count - returns the number of cassette
devices in the machine
-------------------------------------------------*/
INLINE int cassette_count( running_machine *machine )
{
int count = 0;
device_t *device = machine->m_devicelist.first(CASSETTE);
while ( device )
{
count++;
device = device->typenext();
}
return count;
}
/*-------------------------------------------------
bitbanger_count - returns the number of bitbanger
devices in the machine
-------------------------------------------------*/
INLINE int bitbanger_count( running_machine *machine )
{
int count = 0;
device_t *device = machine->m_devicelist.first(BITBANGER);
while ( device )
{
count++;
device = device->typenext();
}
return count;
}
/*-------------------------------------------------
tapecontrol_gettime - returns a textual
representation of the time
-------------------------------------------------*/
astring *tapecontrol_gettime(astring *dest, device_t *device, int *curpos, int *endpos)
{
double t0, t1;
t0 = cassette_get_position(device);
t1 = cassette_get_length(device);
if (t1)
astring_printf(dest, "%04d/%04d", (int) t0, (int) t1);
else
astring_printf(dest, "%04d/%04d", 0, (int) t1);
if (curpos != NULL)
*curpos = t0;
if (endpos != NULL)
*endpos = t1;
return dest;
}
/*-------------------------------------------------
menu_tape_control_populate - populates the
main tape control menu
-------------------------------------------------*/
static void menu_tape_control_populate(running_machine *machine, ui_menu *menu, tape_control_menu_state *menustate)
{
astring timepos;
cassette_state state;
int count = cassette_count(machine);
UINT32 flags = 0;
if( count > 0 )
{
if( menustate->index == (count-1) )
flags |= MENU_FLAG_LEFT_ARROW;
else
flags |= MENU_FLAG_RIGHT_ARROW;
}
if (menustate->device->exists())
{
double t0, t1;
UINT32 tapeflags = 0;
t0 = cassette_get_position(&menustate->device->device());
t1 = cassette_get_length(&menustate->device->device());
if (t1 > 0)
{
if (t0 > 0)
tapeflags |= MENU_FLAG_LEFT_ARROW;
if (t0 < t1)
tapeflags |= MENU_FLAG_RIGHT_ARROW;
}
/* name of tape */
ui_menu_item_append(menu, menustate->device->image_config().devconfig().name(), menustate->device->filename(), flags, TAPECMD_SELECT);
/* state */
tapecontrol_gettime(&timepos, &menustate->device->device(), NULL, NULL);
state = cassette_get_state(&menustate->device->device());
ui_menu_item_append(
menu,
(state & CASSETTE_MASK_UISTATE) == CASSETTE_STOPPED
? "stopped"
: ((state & CASSETTE_MASK_UISTATE) == CASSETTE_PLAY
? ((state & CASSETTE_MASK_MOTOR) == CASSETTE_MOTOR_ENABLED ? "playing" : "(playing)")
: ((state & CASSETTE_MASK_MOTOR) == CASSETTE_MOTOR_ENABLED ? "recording" : "(recording)")
),
astring_c(&timepos),
tapeflags,
TAPECMD_SLIDER);
/* pause or stop */
ui_menu_item_append(menu, "Pause/Stop", NULL, 0, TAPECMD_STOP);
/* play */
ui_menu_item_append(menu, "Play", NULL, 0, TAPECMD_PLAY);
/* record */
ui_menu_item_append(menu, "Record", NULL, 0, TAPECMD_RECORD);
/* rewind */
ui_menu_item_append(menu, "Rewind", NULL, 0, TAPECMD_REWIND);
/* fast forward */
ui_menu_item_append(menu, "Fast Forward", NULL, 0, TAPECMD_FAST_FORWARD);
}
else
{
/* no tape loaded */
ui_menu_item_append(menu, "No Tape Image loaded", NULL, flags, NULL);
}
}
/*-------------------------------------------------
menu_bitbanger_control_populate - populates the
main bitbanger control menu
-------------------------------------------------*/
static void menu_bitbanger_control_populate(running_machine *machine, ui_menu *menu, bitbanger_control_menu_state *menustate)
{
int count = bitbanger_count(machine);
UINT32 flags = 0, mode_flags = 0, baud_flags = 0, tune_flags = 0;
if( count > 0 )
{
if( menustate->index == (count-1) )
flags |= MENU_FLAG_LEFT_ARROW;
else
flags |= MENU_FLAG_RIGHT_ARROW;
}
if (bitbanger_inc_mode(&menustate->device->device(), TRUE))
mode_flags |= MENU_FLAG_RIGHT_ARROW;
if (bitbanger_dec_mode(&menustate->device->device(), TRUE))
mode_flags |= MENU_FLAG_LEFT_ARROW;
if (bitbanger_inc_baud(&menustate->device->device(), TRUE))
baud_flags |= MENU_FLAG_RIGHT_ARROW;
if (bitbanger_dec_baud(&menustate->device->device(), TRUE))
baud_flags |= MENU_FLAG_LEFT_ARROW;
if (bitbanger_inc_tune(&menustate->device->device(), TRUE))
tune_flags |= MENU_FLAG_RIGHT_ARROW;
if (bitbanger_dec_tune(&menustate->device->device(), TRUE))
tune_flags |= MENU_FLAG_LEFT_ARROW;
if (menustate->device->exists())
{
/* name of bitbanger file */
ui_menu_item_append(menu, menustate->device->image_config().devconfig().name(), menustate->device->filename(), flags, BITBANGERCMD_SELECT);
ui_menu_item_append(menu, "Device Mode:", bitbanger_mode_string(&menustate->device->device()), mode_flags, BITBANGERCMD_MODE);
ui_menu_item_append(menu, "Baud:", bitbanger_baud_string(&menustate->device->device()), baud_flags, BITBANGERCMD_BAUD);
ui_menu_item_append(menu, "Baud Tune:", bitbanger_tune_string(&menustate->device->device()), tune_flags, BITBANGERCMD_TUNE);
ui_menu_item_append(menu, "Protocol:", "8-1-N", 0, NULL);
}
else
{
/* no tape loaded */
ui_menu_item_append(menu, "No Bitbanger Image loaded", NULL, flags, NULL);
}
}
/*-------------------------------------------------
menu_tape_control - main tape control menu
-------------------------------------------------*/
void ui_mess_menu_tape_control(running_machine *machine, ui_menu *menu, void *parameter, void *state)
{
tape_control_menu_state *menustate;
const ui_menu_event *event;
/* if no state, allocate some */
if (state == NULL)
state = ui_menu_alloc_state(menu, sizeof(*menustate), NULL);
menustate = (tape_control_menu_state *) state;
/* do we have to load the device? */
if (menustate->device == NULL)
{
int index = menustate->index;
device_image_interface *device = NULL;
for (bool gotone = machine->m_devicelist.first(device); gotone; gotone = device->next(device))
{
if(device->device().type() == CASSETTE) {
if (index==0) break;
index--;
}
}
menustate->device = device;
ui_menu_reset(menu, (ui_menu_reset_options)0);
}
/* rebuild the menu - we have to do this so that the counter updates */
ui_menu_reset(menu, UI_MENU_RESET_REMEMBER_POSITION);
menu_tape_control_populate(machine, menu, (tape_control_menu_state*)state);
/* process the menu */
event = ui_menu_process(machine, menu, UI_MENU_PROCESS_LR_REPEAT);
if (event != NULL)
{
switch(event->iptkey)
{
case IPT_UI_LEFT:
if (event->itemref==TAPECMD_SLIDER)
cassette_seek(&menustate->device->device(), -1, SEEK_CUR);
else
if (event->itemref==TAPECMD_SELECT)
{
/* left arrow - rotate left through cassette devices */
if (menustate->index > 0)
menustate->index--;
else
menustate->index = cassette_count(machine) - 1;
menustate->device = NULL;
}
break;
case IPT_UI_RIGHT:
if (event->itemref==TAPECMD_SLIDER)
cassette_seek(&menustate->device->device(), +1, SEEK_CUR);
else
if (event->itemref==TAPECMD_SELECT)
{
/* right arrow - rotate right through cassette devices */
if (menustate->index < cassette_count(machine) - 1)
menustate->index++;
else
menustate->index = 0;
menustate->device = NULL;
}
break;
case IPT_UI_SELECT:
{
if (event->itemref==TAPECMD_STOP)
cassette_change_state(&menustate->device->device(), CASSETTE_STOPPED, CASSETTE_MASK_UISTATE);
else
if (event->itemref==TAPECMD_PLAY)
cassette_change_state(&menustate->device->device(), CASSETTE_PLAY, CASSETTE_MASK_UISTATE);
else
if (event->itemref==TAPECMD_RECORD)
cassette_change_state(&menustate->device->device(), CASSETTE_RECORD, CASSETTE_MASK_UISTATE);
else
if (event->itemref==TAPECMD_REWIND)
cassette_seek(&menustate->device->device(), -30, SEEK_CUR);
else
if (event->itemref==TAPECMD_FAST_FORWARD)
cassette_seek(&menustate->device->device(), 30, SEEK_CUR);
else
if (event->itemref==TAPECMD_SLIDER)
cassette_seek(&menustate->device->device(), 0, SEEK_SET);
}
break;
}
}
}
/*-------------------------------------------------
menu_bitbanger_control - main bitbanger
control menu
-------------------------------------------------*/
void ui_mess_menu_bitbanger_control(running_machine *machine, ui_menu *menu, void *parameter, void *state)
{
bitbanger_control_menu_state *menustate;
const ui_menu_event *event;
/* if no state, allocate some */
if (state == NULL)
state = ui_menu_alloc_state(menu, sizeof(*menustate), NULL);
menustate = (bitbanger_control_menu_state *) state;
/* do we have to load the device? */
if (menustate->device == NULL)
{
int index = menustate->index;
device_image_interface *device = NULL;
for (bool gotone = machine->m_devicelist.first(device); gotone; gotone = device->next(device))
{
if(device->device().type() == BITBANGER) {
if (index==0) break;
index--;
}
}
menustate->device = device;
ui_menu_reset(menu, (ui_menu_reset_options)0);
}
/* rebuild the menu */
ui_menu_reset(menu, UI_MENU_RESET_REMEMBER_POSITION);
menu_bitbanger_control_populate(machine, menu, (bitbanger_control_menu_state*)state);
/* process the menu */
event = ui_menu_process(machine, menu, UI_MENU_PROCESS_LR_REPEAT);
if (event != NULL)
{
switch(event->iptkey)
{
case IPT_UI_LEFT:
if (event->itemref==BITBANGERCMD_SELECT)
{
/* left arrow - rotate left through cassette devices */
if (menustate->index > 0)
menustate->index--;
else
menustate->index = bitbanger_count(machine) - 1;
menustate->device = NULL;
}
else if (event->itemref==BITBANGERCMD_MODE)
{
bitbanger_dec_mode(&menustate->device->device(), FALSE);
}
else if (event->itemref==BITBANGERCMD_BAUD)
{
bitbanger_dec_baud(&menustate->device->device(), FALSE);
}
else if (event->itemref==BITBANGERCMD_TUNE)
{
bitbanger_dec_tune(&menustate->device->device(), FALSE);
}
break;
case IPT_UI_RIGHT:
if (event->itemref==BITBANGERCMD_SELECT)
{
/* right arrow - rotate right through cassette devices */
if (menustate->index < bitbanger_count(machine) - 1)
menustate->index++;
else
menustate->index = 0;
menustate->device = NULL;
}
else if (event->itemref==BITBANGERCMD_MODE)
{
bitbanger_inc_mode(&menustate->device->device(), FALSE);
}
else if (event->itemref==BITBANGERCMD_BAUD)
{
bitbanger_inc_baud(&menustate->device->device(), FALSE);
}
else if (event->itemref==BITBANGERCMD_TUNE)
{
bitbanger_inc_tune(&menustate->device->device(), FALSE);
}
break;
}
}
}

View File

@ -24,4 +24,8 @@ void ui_image_menu_file_manager(running_machine *machine, ui_menu *menu, void *p
void ui_image_menu_image_info(running_machine *machine, ui_menu *menu, void *parameter, void *state); void ui_image_menu_image_info(running_machine *machine, ui_menu *menu, void *parameter, void *state);
void ui_mess_menu_bitbanger_control(running_machine *machine, ui_menu *menu, void *parameter, void *state);
void ui_mess_menu_tape_control(running_machine *machine, ui_menu *menu, void *parameter, void *state);
#endif /* __UIIMAGE_H__ */ #endif /* __UIIMAGE_H__ */

View File

@ -19,12 +19,9 @@
#include "uimenu.h" #include "uimenu.h"
#include "audit.h" #include "audit.h"
#include "crsshair.h" #include "crsshair.h"
#ifdef MESS
#include "uimess.h"
#endif /* MESS */
#include <ctype.h> #include <ctype.h>
#include "imagedev/cassette.h"
#include "imagedev/bitbngr.h"
@ -1549,10 +1546,14 @@ static void menu_main_populate(running_machine *machine, ui_menu *menu, void *st
/* add file manager menu */ /* add file manager menu */
ui_menu_item_append(menu, "File Manager", NULL, 0, (void*)ui_image_menu_file_manager); ui_menu_item_append(menu, "File Manager", NULL, 0, (void*)ui_image_menu_file_manager);
#ifdef MESS
/* add MESS-specific menus */ /* add tape control menu */
ui_mess_main_menu_populate(machine, menu); if (machine->m_devicelist.first(CASSETTE))
#endif /* MESS */ ui_menu_item_append(menu, "Tape Control", NULL, 0, (void*)ui_mess_menu_tape_control);
/* add bitbanger control menu */
if (machine->m_devicelist.first(BITBANGER))
ui_menu_item_append(menu, "Bitbanger Control", NULL, 0, (void*)ui_mess_menu_bitbanger_control);
} }
/* add keyboard mode menu */ /* add keyboard mode menu */
if (input_machine_has_keyboard(machine) && inputx_can_post(machine)) if (input_machine_has_keyboard(machine) && inputx_can_post(machine))

View File

@ -271,9 +271,7 @@ a tilemap-like structure, from which data is copied)
#include "cpu/sh2/sh2.h" #include "cpu/sh2/sh2.h"
#include "cpu/sh2/sh2comn.h" #include "cpu/sh2/sh2comn.h"
#include "sound/cdda.h" #include "sound/cdda.h"
#ifdef MESS #include "imagedev/chd_cd.h"
#include "devices/chd_cd.h"
#endif
#include "sound/rf5c68.h" #include "sound/rf5c68.h"
#define MEGADRIV_VDP_VRAM(address) megadrive_vdp_vram[(address)&0x7fff] #define MEGADRIV_VDP_VRAM(address) megadrive_vdp_vram[(address)&0x7fff]

View File

@ -22,9 +22,7 @@
***************************************************************************/ ***************************************************************************/
#include "emu.h" #include "emu.h"
#ifdef MESS #include "imagedev/chd_cd.h"
#include "devices/chd_cd.h"
#endif
#include "cdrom.h" #include "cdrom.h"
#include "stvcd.h" #include "stvcd.h"

View File

@ -72,12 +72,6 @@
#include "strconv.h" #include "strconv.h"
#include "config.h" #include "config.h"
#ifdef MESS
#include "uimess.h"
#endif
//============================================================ //============================================================
// PARAMETERS // PARAMETERS
//============================================================ //============================================================